KTV歌曲推薦-PCA降維+邏輯迴歸-性別預測及過擬合處理

前言

上一篇使用邏輯迴歸預測了用戶性別,因爲矩陣比較稀疏因此會影響訓練速度。因此考慮降維,降維方案有不少,本次只考慮PCA和SVD。python

PCA和SVD原理

有興趣的能夠本身去研究一下 https://medium.com/@jonathan_hui/machine-learning-singular-value-decomposition-svd-principal-component-analysis-pca-1d45e885e491網絡

我簡述一下:dom

  • PCA是將高維數據映射到低維座標系中,讓數據儘可能稀疏
  • SVD就是非方陣的PCA
  • 實際使用中SVD和PCA並沒有太大區別
  • 若是特徵大於數據記錄數,並不能有好的效果,具體緣由本身能夠去看。

代碼

數據獲取和處理

之前文章寫過不少次,這裏略過 原數據shape爲:2000*1900函數

PCA和矩陣轉換

查看最佳維度數

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
pca = PCA().fit(song_hot_matrix)
plt.plot(np.cumsum(pca.explained_variance_ratio_))
plt.xlabel('number of components')
plt.ylabel('cumulative explained variance');

從圖中能夠看出大概1500維度已經能夠達到90+解釋性測試

保留99%矩陣解釋性

pca = PCA(n_components=0.99, whiten=True)
song_hot_matrix_pca = pca.fit_transform(song_hot_matrix)

獲得壓縮後特徵爲: 2000*1565 並無壓縮多少優化

模型訓練

import os
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"   # see issue #152
os.environ["CUDA_VISIBLE_DEVICES"] = ""

import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Activation, Embedding,Flatten,Dropout
import matplotlib.pyplot as plt
from keras.utils import np_utils
from sklearn import datasets
from sklearn.model_selection import train_test_split

n_class=user_decades_encoder.get_class_count()
song_count=song_label_encoder.get_class_count()
print(n_class)
print(song_count)

train_X,test_X, train_y, test_y = train_test_split(song_hot_matrix_pca,
                                                   decades_hot_matrix,
                                                   test_size = 0.2,
                                                   random_state = 0)
train_count = np.shape(train_X)[0]
# 構建神經網絡模型
model = Sequential()
model.add(Dense(input_dim=song_hot_matrix_pca.shape[1], units=n_class))
model.add(Activation('softmax'))

# 選定loss函數和優化器
model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])

# 訓練過程
print('Training -----------')
for step in range(train_count):
    scores = model.train_on_batch(train_X, train_y)
    if step % 50 == 0:
        print("訓練樣本 %d 個, 損失: %f, 準確率: %f" % (step, scores[0], scores[1]*100))
print('finish!')

訓練結果:ui

訓練樣本 4750 個, 損失: 0.371499, 準確率: 83.207470
訓練樣本 4800 個, 損失: 0.381518, 準確率: 82.193959
訓練樣本 4850 個, 損失: 0.364363, 準確率: 83.763909
訓練樣本 4900 個, 損失: 0.378466, 準確率: 82.551670
訓練樣本 4950 個, 損失: 0.391976, 準確率: 81.756759
訓練樣本 5000 個, 損失: 0.378810, 準確率: 83.505565

測試集驗證:編碼

# 準確率評估
from sklearn.metrics import classification_report
scores = model.evaluate(test_X, test_y, verbose=0)
print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))


Y_test = np.argmax(test_y, axis=1)
y_pred = model.predict_classes(song_hot_matrix_pca.transform(test_X))
print(classification_report(Y_test, y_pred))

accuracy: 50.20%lua

很明顯已通過擬合code

處理過擬合-增長Dropout

這裏使用加Dropout,隨機丟棄特徵的方式處理過擬合,代碼:

# 構建神經網絡模型
model = Sequential()
model.add(Dropout(0.5))
model.add(Dense(input_dim=song_hot_matrix_pca.shape[1], units=n_class))
model.add(Activation('softmax'))

accuracy:70%

處理過擬合-L1L2正則

這裏給權重增長正則

# 構建神經網絡模型
model = Sequential()
model.add(Dense(input_dim=song_hot_matrix_pca.shape[1], units=n_class, kernel_regularizer=regularizers.l2(0.01)))
model.add(Activation('softmax'))

accuracy:62%

Well Done

其實SVD的作法與PCA相似,這裏再也不演示。通過我測試發現,在個人數據集上,PCA雖然加快了訓練速度,可是丟棄了太多特徵,致使數據很容易過擬合。加入Dropout或者增長正則相能夠改善過擬合的狀況,下一篇會分享自編碼降維。

相關文章
相關標籤/搜索