2019年1月8日 星期二

深度學習 - Reuters 路透社數據練習 - 多分類問題

深度學習 - Reuters 路透社數據練習 - 多分類問題

from keras.datasets import reuters

(train_data, train_labels), (test_data, test_labels) = reuters.load_data(
                                                       num_words=10000)


先來了解一下數據的形狀,
>>> len(train_data)
8982
>>> len(test_data)
2246
>>> max([max(sequence) for sequence in train_data])
9999
>>> max(train_labels)
45
>>> min(train_labels)
0

其實跟IMDb 是差不多的,都是文字的組成,經過keras的處理,已經轉換成數字list,總共有8982組訓練data,2246組驗證data。而這次不是二分類而是多分類、多標籤multilabel, multiclass classification 問題,將文章分成46個大類 (0,45)。

用一樣的方法"one-hot 編碼",是一種分類編碼(categorical encoding),之後會再學到其原理。
將數據向量化:
def vectorize_sequences(sequences, dimension=10000):
    results = np.zeros((len(sequences), dimension))
    for i, sequence in enumerate(sequences):
        results[i, sequence] = 1.    
    return results

x_train = vectorize_sequences(train_data)
x_test = vectorize_sequences(test_data)

不一樣的是,這裡也將標籤也向量化,因為多分類的關係:
def to_one_hot(labels, dimension=46):
    results = np.zeros((len(labels), dimension))
    for i, label in enumerate(labels):
        results[i, label] = 1.    
    return results

one_hot_train_labels = to_one_hot(train_labels)
one_hot_test_labels = to_one_hot(test_labels)

向量化後的 one_hot_train_label[0] 會是一個44個0,一個1的array。
>>>train_labels[0]
3
>>>one_hot_test_labels[0]
array([0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])


建立網絡訓練模型,一樣使用Sequential()

from keras import models
from keras import layers

model = models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(46, activation='softmax'))
這邊有個條件限制,就是隱藏單元的維度不能只有像IMDb的16維,因為這個多分類的問題有46個分類,16個維度太小,可能會造成訓練過程丟失了與分類相關的訊息,而在迭代過程中永遠無法找回,所以維度較小的層會照成訓練的瓶頸,我們在這邊設定64看看。


選擇優化器rmsprop,損失函數categorical_crossentropy,精度accuracy

model.compile(optimizer='rmsprop',              
              loss='categorical_crossentropy',
              metrics=['accuracy'])
這邊選用 categorical_crossentropy(y_true, y_pred) 分類交叉熵

Keras文本說明:
當使用 categorical_crossentropy 損失時,你的目標值應該是分類格式 (即,如果你有 10 個類,每個樣本的目標值應該是一個 10 维的向量,這個向量除了表示類别的那個索引為 1,其他均為 0)。 為了將整數目標值轉換為分類目標值,你可以使用 Keras 實用函數 to_categorical:

from keras.utils.np_utils import to_categorical
categorical_labels = to_categorical(int_labels, num_classes=None)

Ling之博客 :

特點:
1)其中n為樣本數,c為label類別,主要適用於one-hot
2)一定配合softmax
3)適用於多分類問題
4)必須是one-hot類型的vector作為y值

監督學習 - validation_data

留出驗證資料 取前1000組做驗證資料
x_val = x_train[:1000]
partial_x_train = x_train[1000:]

y_val = one_hot_train_labels[:1000]
partial_y_train = one_hot_train_labels[1000:]

丟進fit學習,並將學習過程繪製出來
history = model.fit(partial_x_train,
                    partial_y_train,
                    epochs=20,
                    batch_size=512,
                    validation_data=(x_val, y_val))

import matplotlib.pyplot as plt

loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(1, len(loss) + 1)

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.show()
plt.clf()

acc = history.history['acc']
val_acc = history.history['val_acc']

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.show()


可以從數據資料看出,驗證loss&驗證acc跟epochs的關係
>>>min(val_loss)
Out[5]: 0.891695858001709  發生在epochs :10/20 的時候
>>>max(val_acc)
Out[6]: 0.8150000138282776  發生在epochs :16/20 的時候

分別嘗試epochs : 10 & 16 在測試數據上的表現。
history = model.fit(partial_x_train,
                    partial_y_train,
                    epochs=10,
                    batch_size=512,
                    validation_data=(x_val, y_val))

results = model.evaluate(x_test, one_hot_test_labels)
print('epochs=10,results=',results)
epochs=10,results= [1.008357546102332, 0.7804986642920748]
epochs=16,results= [1.2029922276018776, 0.7773820124666073]
epochs=9,results= [0.9811730119445339, 0.7880676759212865]

利用監督學習後,選擇epochs 9~10 可以得到測試數據精度在0.788左右。






沒有留言:

張貼留言