深度學習 - 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),之後會再學到其原理。
將數據向量化:
不一樣的是,這裡也將標籤也向量化,因為多分類的關係:
向量化後的 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.])
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左右。
沒有留言:
張貼留言