fetch_lfw_peopleデータを標準化して分類学習の精度向上するのか?

  • 入力データの標準化による改善をしてみよう
  • confusion matrix で指標を見てみる
In [1]:
from sklearn.datasets import fetch_lfw_people

from sklearn.model_selection import train_test_split # 学習データと検証用データ分割用ライブラリ
from sklearn.preprocessing import StandardScaler # 標準化ライブラリ
from sklearn import decomposition                # 主成分分析用ライブラリ
from sklearn import svm                          # SVC用ライブラリ
from sklearn import metrics                      # 指標データ用ライブラリ

from matplotlib import pyplot as plt

画像ロード

  • data :画像数は1140個。1画像は2914( 縦62×横47)
  • imges :画像形式の配列(各dataをreshape(62,47)した形態)
  • target :分類結果(dataを分類した場合の正解データになる値)
  • target_names : 分類結果(target)の値に対応する人物名(文字列)
In [2]:
lfw = fetch_lfw_people(data_home='./scikit_learn_data/', min_faces_per_person=100, resize=0.5)

データを学習用データと検証用データに分ける

  • 1/4を検証用データとする
In [3]:
X = lfw.data
y = lfw.target
X_train, X_test, y_train, y_test = train_test_split(lfw.data, lfw.target, test_size=0.25, random_state=0)

# 学習用データ数と検証用データ数
print('num of train data:', X_train.shape[0],
      '\nnum of test  data:', X_test.shape[0])
num of train data: 855 
num of test  data: 285
In [4]:
v,h = lfw.images.shape[1:3] # 画像の垂直・水平サイズを保持する
n_train = X_train.shape[0]  # 学習データ数を保持する

主成分分析(Principal Component Analysis)で次元圧縮

In [5]:
pca=decomposition.PCA(n_components=0.95, svd_solver = 'full', random_state=0)
pca.fit(X_train)
X_train_pca = pca.transform(X_train)
X_test_pca  = pca.transform(X_test)
X_train_inv = pca.inverse_transform(X_train_pca)

print('----------\n 主成分の数:', pca.n_components_)
----------
 主成分の数: 145

LinearSVCで学習

In [6]:
linSVC=svm.LinearSVC()
linSVC.fit(X_train_pca, y_train)
C:\Anaconda3\envs\AI\lib\site-packages\sklearn\svm\_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
Out[6]:
LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True,
          intercept_scaling=1, loss='squared_hinge', max_iter=1000,
          multi_class='ovr', penalty='l2', random_state=None, tol=0.0001,
          verbose=0)
In [7]:
y_pred_pca=linSVC.predict(X_test_pca)

print('----------\n 検証用データの正解率',     linSVC.score(X_test_pca,y_test))
print('----------\n classification_report\n', metrics.classification_report(y_test, y_pred_pca, target_names=lfw.target_names))
print('----------\n confusion_matrix\n',      metrics.confusion_matrix(y_test, y_pred_pca))

plt.rcParams["figure.figsize"]=(10,10)
metrics.ConfusionMatrixDisplay(confusion_matrix=metrics.confusion_matrix(y_test, y_pred_pca), display_labels=lfw.target_names).plot(cmap='YlGn', values_format='d')
plt.savefig('.\cmat_nostd.jpg') 
----------
 検証用データの正解率 0.7052631578947368
----------
 classification_report
                    precision    recall  f1-score   support

     Colin Powell       0.70      0.69      0.69        61
  Donald Rumsfeld       0.48      0.78      0.60        36
    George W Bush       0.86      0.80      0.83       122
Gerhard Schroeder       0.64      0.45      0.53        31
       Tony Blair       0.61      0.54      0.58        35

         accuracy                           0.71       285
        macro avg       0.66      0.65      0.64       285
     weighted avg       0.72      0.71      0.71       285

----------
 confusion_matrix
 [[42  8  4  1  6]
 [ 3 28  4  1  0]
 [ 9 11 98  1  3]
 [ 4  6  4 14  3]
 [ 2  5  4  5 19]]

標準化したデータで主成分分析・学習を再度行う

StandardScalerで標準化

In [8]:
sc = StandardScaler()
sc.fit(X_train)

X_train_std = sc.transform(X_train)
X_test_std  = sc.transform(X_test)

主成分分析(Principal Component Analysis)で次元圧縮

In [9]:
pca=decomposition.PCA(n_components=0.95, svd_solver = 'full', random_state=0)
pca.fit(X_train_std)
X_train_std_pca = pca.transform(X_train_std)
X_test_std_pca = pca.transform(X_test_std)
X_train_std_inv=pca.inverse_transform(X_train_std_pca)

print('----------\n 主成分の数:', pca.n_components_)
----------
 主成分の数: 148

LinearSVCで学習

In [10]:
linSVC.fit(X_train_std_pca, y_train)
C:\Anaconda3\envs\AI\lib\site-packages\sklearn\svm\_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
Out[10]:
LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True,
          intercept_scaling=1, loss='squared_hinge', max_iter=1000,
          multi_class='ovr', penalty='l2', random_state=None, tol=0.0001,
          verbose=0)
In [11]:
y_pred_std_pca=linSVC.predict(X_test_std_pca)

print('----------\n 検証用データの正解率',     linSVC.score(X_test_std_pca,y_test))
print('----------\n classification_report\n', metrics.classification_report(y_test, y_pred_std_pca, target_names=lfw.target_names))
print('----------\n confusion_matrix\n',      metrics.confusion_matrix(y_test, y_pred_std_pca))

plt.rcParams["figure.figsize"]=(10,10)
metrics.ConfusionMatrixDisplay(confusion_matrix=metrics.confusion_matrix(y_test, y_pred_std_pca), display_labels=lfw.target_names).plot(cmap='YlGn', values_format='d')
plt.savefig('.\cmat_std.jpg') 
----------
 検証用データの正解率 0.7929824561403509
----------
 classification_report
                    precision    recall  f1-score   support

     Colin Powell       0.83      0.79      0.81        61
  Donald Rumsfeld       0.73      0.61      0.67        36
    George W Bush       0.84      0.85      0.85       122
Gerhard Schroeder       0.68      0.81      0.74        31
       Tony Blair       0.75      0.77      0.76        35

         accuracy                           0.79       285
        macro avg       0.77      0.77      0.76       285
     weighted avg       0.79      0.79      0.79       285

----------
 confusion_matrix
 [[ 48   2   6   1   4]
 [  2  22   7   2   3]
 [  7   4 104   5   2]
 [  0   2   4  25   0]
 [  1   0   3   4  27]]

Powellさんの正解率が下がっていますが、全体的な向上が見られました。

標準化による入力データの違いを比較してみました。

  • コントラストが調整されているのがわかりますね。
In [12]:
plt.rcParams["figure.figsize"]=(15,10)

for i in range(5):
    subplt = plt.subplot(4,5, i+1)
    subplt.imshow(X_train.reshape(n_train,v,h)[i], cmap='gray')
    
for i in range(5):
    subplt = plt.subplot(4,5, (i+1)+5)
    subplt.imshow(X_train_std.reshape(n_train,v,h)[i], cmap='gray')
    
plt.savefig('./std.jpg')
plt.show()
In [ ]:
 
In [ ]: