【Python】 KNNによるデータの分類
書籍「PYTHON機械学習プログラミング」のKNNによるデータの分類例をメモします。
# -*- coding: utf-8 -*- import numpy as np from matplotlib.colors import ListedColormap from matplotlib import pyplot as plt from sklearn.neighbors import KNeighborsClassifier def plot_decision_regions(X, y, classifier, resolution=0.02): # マーカーとカラーマップの準備 markers = ('s', 'x', 'o', '^', 'v') colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan') cmap = ListedColormap(colors[:len(np.unique(y))]) # 領域の最大最小値 x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1 x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1 # グリッドポイントの生成 xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution), np.arange(x2_min, x2_max, resolution)) # 予測を実行する Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T) # 予測結果をプロットする Z = Z.reshape(xx1.shape) plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap) plt.xlim(xx1.min(), xx1.max()) plt.ylim(xx2.min(), xx2.max()) for i, cls in enumerate(np.unique(y)): plt.scatter(X[y==cls, 0], X[y==cls, 1], alpha=0.8, c=cmap(i), marker=markers[i], label=cls) plt.show() if __name__ == '__main__': # データの生成 np.random.seed(0) X1 = np.random.randn(50, 2) y1 = np.ones(50) X2 = np.random.randn(50, 2) + 10 y2 = np.ones(50)*2 X3 = np.random.randn(50, 2) X3[:, 1] += 10 y3 = np.ones(50)*3 X4 = np.random.randn(50, 2) X4[:, 0] += 10 y4 = np.ones(50)*4 X = np.concatenate((X1, X2, X3, X4)) y = np.concatenate((y1, y2, y3, y4)) # KNNによる分類 knn = KNeighborsClassifier(n_neighbors=4) knn.fit(X, y) # 分類結果を表示する plot_decision_regions(X, y, knn)
Python機械学習プログラミング 達人データサイエンティストによる理論と実践 (impress top gear)
- 作者: Sebastian Raschka,株式会社クイープ,福島真太朗
- 出版社/メーカー: インプレス
- 発売日: 2016/06/30
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (4件) を見る
【Python】 SVMによるデータの分類
書籍「PYTHON機械学習プログラミング」を読んでいて、SVMによるXORデータの分類例があったのですが、分類結果をグラフ化する部分が勉強になったのでメモします。
# -*- coding: utf-8 -*- import numpy as np from matplotlib.colors import ListedColormap from matplotlib import pyplot as plt from sklearn.svm import SVC def plot_decision_regions(X, y, classifier, resolution=0.02): # マーカーとカラーマップの準備 markers = ('s', 'x', 'o', '^', 'v') colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan') cmap = ListedColormap(colors[:len(np.unique(y))]) # 領域の最大最小値 x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1 x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1 # グリッドポイントの生成 xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution), np.arange(x2_min, x2_max, resolution)) # 予測を実行する Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T) # 予測結果をプロットする Z = Z.reshape(xx1.shape) plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap) plt.xlim(xx1.min(), xx1.max()) plt.ylim(xx2.min(), xx2.max()) for i, cls in enumerate(np.unique(y)): plt.scatter(X[y==cls, 0], X[y==cls, 1], alpha=0.8, c=cmap(i), marker=markers[i], label=cls) plt.show() if __name__ == '__main__': # データの生成 np.random.seed(0) X = np.random.randn(200, 2) y = np.logical_xor(X[:, 0] > 0, X[:, 1] > 0) y = np.where(y, 1, -1) # SVMによるフィッティング svm = SVC(gamma='auto') # γを大きくし過ぎると過適合してしまう svm.fit(X, y) # 分類結果を表示する plot_decision_regions(X, y, svm)
Python機械学習プログラミング 達人データサイエンティストによる理論と実践 (impress top gear)
- 作者: Sebastian Raschka,株式会社クイープ,福島真太朗
- 出版社/メーカー: インプレス
- 発売日: 2016/06/30
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (4件) を見る
【Python】 Kerasで中間層を可視化する
Kerasを利用してネットワーク中間層を可視化する方法をメモします。プログラムでは学習済みのモデルと重みがある事を想定し、それらを読み取って一層目の中間層であるConvolution2Dの重みを可視化しています。
import numpy as np from keras.models import model_from_json from matplotlib import pyplot as plt with open('lenet.json', 'r') as file: model_json = file.read() model = model_from_json(model_json) model.load_weights('lenet_weights.hdf5') # Get 1st layer Convolution2D weights. # In this example, weights.shape is (6, 1, 5, 5) weights = model.layers[0].get_weights()[0].transpose(3,2,0,1) fig = plt.figure() for i, weight_3d in enumerate(weights): for j, weight_2d in enumerate(weight_3d): sub = fig.add_subplot(weights.shape[0], weight_3d.shape[0], i*weight_3d.shape[0]+j+1) sub.axis('off') sub.imshow(weight_2d, 'Greys') plt.show()
【Python】CIFAR-10画像データを扱う
AlexNet等の実験でCIFAR-10(CIFAR-10 and CIFAR-100 datasets)を利用することがあります。幸いKerasにはデフォルトでCIFAR-10の画像データを取り込む関数があるのですが、諸事情によりこれが利用できなかったのでCIFAR-10を扱うための関数を作成しました。
def load_image_and_label(pickled_files): import numpy as np # Each file contains 10000 images IMAGE_COUNT_PER_FILE = 10000 # Image shape is 32x32x3 ROW = 32 COL = 32 DIM = 3 whole_images = np.empty((IMAGE_COUNT_PER_FILE*len(pickled_files), ROW, COL, DIM)) whole_labels = np.empty(IMAGE_COUNT_PER_FILE*len(pickled_files)) for i, pickled_file in enumerate(pickled_files): dict = _unpickle(pickled_file) images = dict['data'].reshape(IMAGE_COUNT_PER_FILE, DIM, ROW, COL).transpose(0, 2, 3, 1) whole_images[i*IMAGE_COUNT_PER_FILE:(i + 1)*IMAGE_COUNT_PER_FILE, :, :, :] = images labels = dict['labels'] whole_labels[i*IMAGE_COUNT_PER_FILE:(i + 1)*IMAGE_COUNT_PER_FILE] = labels return (whole_images, whole_labels) def _unpickle(pickled_file): import pickle with open(pickled_file, 'rb') as file: # You'll have an error without "encoding='latin1'" dict = pickle.load(file, encoding='latin1') return dict
上記をcifar10_handling.pyとして保存します。次にこの関数を利用する方法ですが、CIFAR-10のサイトからダウンロードできる"cifar-10-batches-py.tar.gz"を解凍しな中に入っている"data_batch_1"等のファイルになります。
import cifar10_handling (X_train, y_train) = cifar10_handling.load_image_and_label(['data_batch_1', 'data_batch_2', 'data_batch_3', 'data_batch_4', 'data_batch_5']) (X_test, y_test) = cifar10_handling.load_image_and_label(['test_batch'])
あとは正規化等の前処理を加えれば実験に使えるデータとなります。
【Python】 Kerasでモデルを図に保存する
Kerasでは作成したモデルはここ(可視化 - Keras Documentation)にあるように簡単に図として保存できるはず、と思ったのですが予想外のトラブルに見舞われたので解決方法をメモします。環境は以下の通りです。
トラブルの内容ですが、"from keras.utils.visualize_util import plot"の部分で"pydotやgraphvizが必要だ"といったような内容のエラーが出ました。そのためまずは
- conda install graphviz
- conda install pydot-ng
を実施したところ、"conda install graphviz"は問題無く終わったのですが、"conda install pydot-ng"はPython3.5では利用できないと言われます。仕方無く代わりに
- pip install pydot
を実行し、モデルの保存を試みたのですが、今度は"from keras.utils.visualize_util import plot"の部分で"module ‘pydot’ has no attribute ‘find_graphviz’“というエラーが出ました。調べてみると、最新版のpydotからはfind_graphvizという関数は無くなっているらしく、最新版ではなくpydot1.1.0をインストールすると良いというアドバイスを見つけました。ところがpydot1.1.0をインストールしようとするとPython3.5では利用できないというエラーが。。。 打つ手無しのため、強硬策としてソースコードを変更することにしました。Anaconda3フォルダ配下の"Lib\site-packages\keras\utils"にvisualize_util.pyがあります。このファイルのfind_graphvizを使っている13-15行目を以下のようにコメントしました。
#if not pydot.find_graphviz(): # raise ImportError('Failed to import pydot. You must install pydot' # ' and graphviz for `pydotprint` to work.')
これでエラーは出なくなると思ったのですが、今度は"dot.exeが見つからない"といった内容のエラーが。。。ただ、このエラーについてはAnaconda3フォルダ配下の"Library\bin\graphviz"を環境変数のPATHに追加し、PCを再起動することで無くなり、無事モデルを図示できるようになりました。まとめると、Kerasでモデルを図として保存するには
- conda install graphviz
- pip install pydot
- visualize_util.pyのfind_graphvizの部分をコメント
- Anaconda3フォルダ配下の"Library\bin\graphviz"を環境変数のPATHに追加し、PCを再起動する
という手順を踏めば良いと思います。
【Python】 KerasでLeNet5っぽいネットワークを作成する
ディープラーニングの原点と言われるLeNet5(http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf)をKerasで実装し、MNISTの手書き文字を学習させました。LeNet5は以下の構造になっています。 “LeNet5っぽい"とタイトルに書いたのは、完全に論文通りには実装できていないためです(活性化関数のカスタマイズ等が必要ですが、現時点でKerasをそこまで使いこなせていません)。この例ではここ(【Python】 MNIST手書き文字データを扱う - 旅行好きなソフトエンジニアの備忘録)で作成したmnist_handlingというモジュールを利用しています。
import mnist_handling import numpy as np from keras.datasets import mnist from keras.models import Sequential from keras.layers import Dense, Dropout, Flatten from keras.layers import Convolution2D, MaxPooling2D from keras.optimizers import SGD from keras.utils import np_utils if __name__ == '__main__': # Load training data training_image_file = 'train-images-idx3-ubyte.gz' training_label_file = 'train-labels-idx1-ubyte.gz' training_images, training_labels = mnist_handling.load_image_and_label(training_image_file, training_label_file) # Load test data test_image_file = 't10k-images-idx3-ubyte.gz' test_label_file = 't10k-labels-idx1-ubyte.gz' test_images, test_labels = mnist_handling.load_image_and_label(test_image_file, test_label_file) # Normalize data training_images = training_images.astype('float32') test_images = test_images.astype('float32') training_images /= 255 test_images /= 255 # Convert class vectors to binary class matrices class_count = 10 training_labels = np_utils.to_categorical(training_labels, class_count) test_labels = np_utils.to_categorical(test_labels, class_count) # Build model model = Sequential() # Layer1 kernel_count_layer1 = 6 kernel_row_layer1 = 5 kernel_col_layer1 = 5 input_shape = (training_images.shape[1], training_images.shape[2], training_images.shape[3]) model.add(Convolution2D(kernel_count_layer1, kernel_row_layer1, kernel_col_layer1, border_mode='same', input_shape=input_shape, activation='tanh')) # Layer2 pool_size_layer2 = (2, 2) model.add(MaxPooling2D(pool_size=pool_size_layer2)) model.add(Dropout(6/16)) # Layer3 kernel_count_layer3 = 16 kernel_row_layer3 = 5 kernel_col_layer3 = 5 model.add(Convolution2D(kernel_count_layer3, kernel_row_layer3, kernel_col_layer3, border_mode='valid', activation='tanh')) # Layer4 pool_size_layer4 = (2, 2) model.add(MaxPooling2D(pool_size=pool_size_layer4)) # Layer5 kernel_count_layer5 = 120 kernel_row_layer5 = 5 kernel_col_layer5 = 5 model.add(Convolution2D(kernel_count_layer5, kernel_row_layer5, kernel_col_layer5, border_mode='valid', activation='tanh')) # Layer6 output_count_layer6 = 84 model.add(Flatten()) model.add(Dense(output_count_layer6, activation='tanh')) # Output layer model.add(Dense(class_count, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer=SGD(), metrics=['accuracy']) # Start training epoch_count = 20 batch_size = 128 model.fit(training_images, training_labels, batch_size=batch_size, nb_epoch=epoch_count, verbose=1, validation_data=(test_images, test_labels)) # Save model model_file_name = 'lenet.json' model_json = model.to_json() with open(model_file_name, 'w') as file: file.write(model_json) # Save weights weight_file_name = 'lenet_weights.hdf5' model.save_weights(weight_file_name)
論文と比較してトレーニングセットに対する正解率は2.5%、テストセットに対する正解率は1%程度低くなりました。論文では二層目、三層目が全結合になっていないため、代わりにドロップアウトを使用したのですが、これによりトレーニングセットに対する正解率がかなり低くなっているのかもしれません。(2017/02/09追記:最適化関数をAdamに変更することで論文と同程度の正解率となりました)
【Python】 MNIST手書き文字データを扱う
手書き文字のサンプルがダウンロードできる"THE MNIST DATABASE of handwritten digits"(MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges)ですが、gzファイルをダウンロードした後のデータ処理ロジックをメモします。mnist_handling.pyというファイルを作成し、以下を記述します。
import gzip import numpy as np def load_image_and_label(gz_image_file_path, gz_label_file_path): images = _load_image(gz_image_file_path) labels = _load_label(gz_label_file_path) return (images, labels) def _load_image(gz_file_path): with gzip.open(gz_file_path, 'rb') as file: content = file.read() # 手書き画像枚数 image_count = int.from_bytes(content[4:8], 'big') # 手書き画像行数 row = int.from_bytes(content[8:12], 'big') # 手書き画像列数 col = int.from_bytes(content[12:16], 'big') # 手書き画像データの読み込み images = np.frombuffer(content, np.uint8, -1, 16) # imagesのshapeは(60000, 28, 28, 1) images = images.reshape(image_count, row, col, 1) return images def _load_label(gz_file_path): with gzip.open(gz_file_path, 'rb') as file: content = file.read() label_count = int.from_bytes(content[4:8], 'big') labels = np.frombuffer(content, np.uint8, -1, 8) return labels
以下はmnist_handlingモジュールの利用例です。
import mnist_handling training_image_file = 'train-images-idx3-ubyte.gz' training_label_file = 'train-labels-idx1-ubyte.gz' training_images, training_labels = mnist_handling.load_image_and_label(training_image_file, training_label_file) test_image_file = 't10k-images-idx3-ubyte.gz' test_label_file = 't10k-labels-idx1-ubyte.gz' test_images, test_labels = mnist_handling.load_image_and_label(test_image_file, test_label_file)