https://blog.csdn.net/zlrai5895/article/details/79560353
多類分類問題本質上可以分解為多個二分類問題,而解決二分類問題的方法有很多。這里我們利用Keras機器學習框架中的ANN(artificial neural network)來解決多分類問題。這里我們采用的例子是著名的UCI Machine Learning Repository中的鳶尾花數據集(iris flower dataset)。
1. 編碼輸出便簽
多類分類問題與二類分類問題類似,需要將類別變量(categorical function)的輸出標簽轉化為數值變量。這個問題在二分類的時候直接轉換為(0,1)(輸出層采用sigmoid函數)或(-1,1)(輸出層采用tanh函數)。類似的,在多分類問題中我們將轉化為虛擬變量(dummy variable):即用one hot encoding方法將輸出標簽的向量(vector)轉化為只在出現對應標簽的那一列為1,其余為0的布爾矩陣。以我們所用的鳶尾花數據為例:
sample, label
1, Iris-setosa 2, Iris-versicolor 3, Iris-virginica
用one hot encoding轉化后如下:
sample, Iris-setosa, Iris-versicolor, Iris-virginica 1, 1, 0, 0 2, 0, 1, 0 3, 0, 0, 1
注意這里不要將label直接轉化成數值變量,如1,2,3,這樣的話與其說是預測問題更像是回歸預測的問題,后者的難度比前者大。(當類別比較多的時候輸出值的跨度就會比較大,此時輸出層的激活函數就只能用linear)
這一步轉化工作我們可以利用keras中的np_utils.to_categorical
函數來進行。
2. 構建神經網絡模型
Keras是基於Theano或Tensorflow底層開發的簡單模塊化的神經網絡框架,因此用Keras搭建網絡結構會比Tensorflow更加簡單。這里我們將使用Keras提供的KerasClassifier類,這個類可以在scikit-learn包中作為Estimator使用,故利用這個類我們就可以方便的調用sklearn包中的一些函數進行數據預處理和結果評估(此為sklearn包中模型(model)的基本類型)。
對於網絡結構,我們采用3層全向連接的,輸入層有4個節點,隱含層有10個節點,輸出層有3個節點的網絡。其中,隱含層的激活函數為relu(rectifier),輸出層的激活函數為softmax。損失函數則相應的選擇categorical_crossentropy(此函數來着theano或tensorflow,具體可以參見這里)(二分類的話一般選擇activation=‘sigmoid’, loss=‘binary_crossentropy’)。
PS:對於多類分類網絡結構而言,增加中間隱含層能夠提升訓練精度,但是所需的計算時間和空間會增大,因此需要測試選擇一個合適的數目,這里我們設為10;此外,每一層的舍棄率(dropout)也需要相應調整(太高容易欠擬合,太低容易過擬合),這里我們設為0.2。
3. 評估模型
這里我們利用評估機器學習模型的經典方法: k折交叉檢驗(k-fold cross validation)。這里我們采用10折(k=10)。
4. 代碼實現
import numpy as np import pandas as pd from keras.models import Sequential from keras.layers import Dense, Dropout from keras.wrappers.scikit_learn import KerasClassifier from keras.utils import np_utils from sklearn.model_selection import train_test_split, KFold, cross_val_score from sklearn.preprocessing import LabelEncoder # load dataset dataframe = pd.read_csv("iris.csv", header=None) dataset = dataframe.values X = dataset[:, 0:4].astype(float) Y = dataset[:, 4] # encode class values as integers encoder = LabelEncoder() encoded_Y = encoder.fit_transform(Y) # convert integers to dummy variables (one hot encoding) dummy_y = np_utils.to_categorical(encoded_Y) # define model structure def baseline_model(): model = Sequential() model.add(Dense(output_dim=10, input_dim=4, activation='relu')) model.add(Dropout(0.2)) model.add(Dense(output_dim=3, input_dim=10, activation='softmax')) # Compile model model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) return model estimator = KerasClassifier(build_fn=baseline_model, nb_epoch=40, batch_size=256) # splitting data into training set and test set. If random_state is set to an integer, the split datasets are fixed. X_train, X_test, Y_train, Y_test = train_test_split(X, dummy_y, test_size=0.3, random_state=0) estimator.fit(X_train, Y_train) # make predictions pred = estimator.predict(X_test) # inverse numeric variables to initial categorical labels init_lables = encoder.inverse_transform(pred) # k-fold cross-validate seed = 42 np.random.seed(seed) # numpy.random.seed()的使用 kfold = KFold(n_splits=10, shuffle=True, random_state=seed) results = cross_val_score(estimator, X, dummy_y, cv=kfold)