【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)