【Python】PCANetを試してみる
教師なし学習で画像の特徴量抽出を行う方法を調べていて以下を見つけたのでMNISTで試してみました。以下記事にgithubへのリンクがあるので、そこのpcanet.pyを写します。 qiita.com
写したpcanet.pyを使い、以下のmain.pyを書いて動作させれば特徴抽出⇒分類の結果を確認することが出来ます。ただし、pcanetのtransformメソッドが非常に時間がかかる(train, validation, test合計で1時間位かかります)ため、MNISTデータの一部だけ使用しており、かつハイパーパラメータチューニングもやっていません。この状態だとHOG⇒分類で94.7%、PCANet⇒分類で96.4%の正解率となりました。今後はPCANetのようなネットワークが他にもないか調べておきたいです。
import numpy as np from datetime import datetime from keras.datasets import mnist from pcanet import PCANet from lightgbm import LGBMClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score from skimage.feature import hog def get_part_of_mnist(ratio_to_use=0.1): test_size = 1.0 - ratio_to_use (X_train, y_train), (X_test, y_test) = mnist.load_data() X_train, X_validation, y_train, y_validation = train_test_split(X_train, y_train, test_size=test_size, stratify=y_train) X_validation, X_dummy, y_validation, y_dummy = train_test_split(X_validation, y_validation, test_size=test_size, stratify=y_validation) X_test, X_dummy, y_test, y_dummy = train_test_split(X_test, y_test, test_size=test_size, stratify=y_test) return X_train, y_train, X_validation, y_validation, X_test, y_test def extract_feature_using_pcanet(X_train, X_validation, X_test): # Arguments are basically passed as tuple in the form (height, width) but int is also allowed. # If int is given, the parameter will be converted into (size, size) implicitly. pcanet = PCANet( image_shape=X_train.shape[1], # the size of an input image # kernel size, kernel step size, and the number of filters in the first layer, respectively filter_shape_l1=2, step_shape_l1=1, n_l1_output=4, # kernel size, kernel step size, and the number of filters in the second layer, respectively filter_shape_l2=2, step_shape_l2=1, n_l2_output=4, block_shape=2 # the size of area to calculate histogram ) # Check whether all pixels can be considered. Raise ValueError if the structure is not valid. # Calling this function is optional. PCANet works without this line. pcanet.validate_structure() pcanet.fit(X_train) # Train PCANet # Trained PCANet behaves as a transformer from images into features. # `images` is a 3d array in the form (n_images, height, width), who are transformed into feature vectors. X_train = pcanet.transform(X_train) X_validation = pcanet.transform(X_validation) X_test = pcanet.transform(X_test) return X_train, X_validation, X_test def extract_feature_using_hog(X_train, X_validation, X_test): features_train = [] for image in X_train: feature = hog(image, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(3, 3)) features_train.append(feature) features_validation = [] for image in X_validation: feature = hog(image, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(3, 3)) features_validation.append(feature) features_test = [] for image in X_test: feature = hog(image, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(3, 3)) features_test.append(feature) return np.array(features_train), np.array(features_validation), np.array(features_test) if __name__ == '__main__': # MNISTデータの一部を取得する X_train, y_train, X_validation, y_validation, X_test, y_test = get_part_of_mnist() # PCANetで特徴量を生成する X_train, X_validation, X_test = extract_feature_using_pcanet(X_train, X_validation, X_test) # HOGで特徴量を生成する #X_train, X_validation, X_test = extract_feature_using_hog(X_train, X_validation, X_test) # LightGBM分類器を生成する model = LGBMClassifier(objective='multiclass', num_leaves=31, learning_rate=0.1, n_estimators=300) model.fit(X_train, y_train, eval_set=[(X_validation, y_validation)], eval_metric='multi_logloss', early_stopping_rounds=5) y_pred = model.predict(X_test) print(accuracy_score(y_test, y_pred)*100)
【PyTorch】モデルがevalモードの時にout of memoryが発生する事への対処法
トランザクション分離レベルについて分かりやすく説明してくれてるサイト
Repeatable Readとか何のことか良く分かっていなかったのですが、下記サイトに助けられました。 qiita.com
【Python】不均衡な2クラスセグメンテーション問題に適用するロス関数のメモ
この論文で不均衡な2クラスセグメンテーション問題に適用するロス関数が提案されていたのでメモします。ディープラーニングを使ったセグメンテーションでデータが極端に不均衡(例えば画像のほとんどが0で、1はちょっとだけ)の場合、工夫をしないと学習が上手くいかないのですが、論文ではロス関数の工夫によりこの問題を回避しようとしています。
下記の記事ではセグメンテーションのロス関数に以下のダイス係数を利用しました。
def dice_coef(y_true, y_pred): y_true = K.flatten(y_true) y_pred = K.flatten(y_pred) intersection = K.sum(y_true * y_pred) return 2.0 * intersection / (K.sum(y_true) + K.sum(y_pred) + 1) def dice_coef_loss(y_true, y_pred): return 1.0 - dice_coef(y_true, y_pred)
論文ではTversky loss functionという関数を提案しており、以下のようになります。ただこれどこかで見たと思ったらIOUの修正バージョンですね。
ALPHA = 0.3 # 0~1.0の値、Precision重視ならALPHAを大きくする BETA = 1.0 - ALPHA # 0~1.0の値、Recall重視ならALPHAを小さくする def tversky_index(y_true, y_pred): y_true = K.flatten(y_true) y_pred = K.flatten(y_pred) intersection = K.sum(y_true * y_pred) false_positive = K.sum((1.0 - y_true) * y_pred) false_negative = K.sum(y_true * (1.0 - y_pred)) return intersection / (intersection + ALPHA*false_positive + BETA*false_negative) def tversky_loss(y_true, y_pred): return 1.0 - tversky_index(y_true, y_pred)
【Python】How to generate one-hot encodings for an array in numpy? - 101 Numpy Exercises
Q:
One-hot encodingを計算しなさい (Kerasのnp_utils.to_categoricalを使えば良いのですが、Keras使わない時のためのメモ) Input:
arr = np.random.randint(1,4, size=6) arr #> array([2, 3, 2, 2, 2, 1])
Output:
#> array([[ 0., 1., 0.], #> [ 0., 0., 1.], #> [ 0., 1., 0.], #> [ 0., 1., 0.], #> [ 0., 1., 0.], #> [ 1., 0., 0.]])
A:
# Input: arr = np.random.randint(1,4, size=6) arr #> array([2, 3, 2, 2, 2, 1]) # Solution: def one_hot_encodings(arr): uniqs = np.unique(arr) out = np.zeros((arr.shape[0], uniqs.shape[0])) for i, k in enumerate(arr): out[i, k-1] = 1 return out one_hot_encodings(arr) #> array([[ 0., 1., 0.], #> [ 0., 0., 1.], #> [ 0., 1., 0.], #> [ 0., 1., 0.], #> [ 0., 1., 0.], #> [ 1., 0., 0.]]) # Method 2: (arr[:, None] == np.unique(arr)).view(np.int8)
【Python】How to find the most frequent value in a numpy array? - 101 Numpy Exercises
【Python】How to sort a 2D array by a column? - 101 Numpy Exercises
Q:
irisデータセットをsepallengthカラムの値でソートしなさい
A:
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data' iris = np.genfromtxt(url, delimiter=',', dtype='object') names = ('sepallength', 'sepalwidth', 'petallength', 'petalwidth', 'species') # Sort by column position 0: SepalLength print(iris[iris[:,0].argsort()][:20]) #> [[b'4.3' b'3.0' b'1.1' b'0.1' b'Iris-setosa'] #> [b'4.4' b'3.2' b'1.3' b'0.2' b'Iris-setosa'] #> [b'4.4' b'3.0' b'1.3' b'0.2' b'Iris-setosa'] #> [b'4.4' b'2.9' b'1.4' b'0.2' b'Iris-setosa']