Reuters數(shù)據(jù)集下載速度慢露筒,可以在我的repo庫中找到下載垮耳,下載后放到~/.keras/datasets/目錄下烘绽,即可正常運行淋昭。
完整代碼 歡迎Fork、Star
構建神經網絡將路透社新聞分類安接,一共有46個類別翔忽。因為有多個類別,屬于多分類問題盏檐,而每條數(shù)據(jù)只屬于一個類別歇式,所以是單標簽多分類問題;如果每條數(shù)據(jù)可以被分到多個類別中胡野,那問題則屬于多標簽多分類問題材失。
路透社數(shù)據(jù)集
Reuters數(shù)據(jù)集發(fā)布在1986年,一系列短新聞及對應話題的數(shù)據(jù)集硫豆;是文本分類問題最常用的小數(shù)據(jù)集龙巨。和IMDB、MNIST數(shù)據(jù)集類似熊响,Reuters數(shù)據(jù)集也可以通過Keras直接下載旨别。
加載數(shù)據(jù)集
from keras.datasets import reuters
(train_data,train_labels), (test_data, test_labels) = reuters.load_data(num_words=10000)
有8982條訓練集,2246條測試集汗茄。
每個樣本表示成整數(shù)列表秸弛。
>>> train_data[10]
[1, 245, 273, 207, 156, 53, 74, 160, 26, 14, 46, 296, 26, 39, 74, 2979,
3554, 14, 46, 4689, 4329, 86, 61, 3499, 4795, 14, 61, 451, 4329, 17, 12]
也可以將整數(shù)列表轉換成原始數(shù)據(jù)[英文句子]
word_index = reuters.get_word_index()# 單詞--下標 對應字典
reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])# 下標-單詞對應字典
decoded_newswire = ' '.join([reverse_word_index.get(i - 3, '?') for i in
train_data[0]]) #偏移3個:0,1,2保留下標,分別表示:“padding,” “start of sequence,” and “unknown.”
準備數(shù)據(jù)
整數(shù)數(shù)據(jù)向量化剔难,與IMDB數(shù)據(jù)集處理方法相同胆屿。
import numpy as np
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)
標簽的向量化有兩種方法:將標簽列表轉換成整數(shù)張量;使用one-hot編碼偶宫。One-hot編碼方式是類別數(shù)據(jù)常用的一種數(shù)據(jù)格式非迹,也稱為categorical encoding。
def to_one_hot(labels, dimension=46):# 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)
Keras中有一個內置的One-hot編碼轉換函數(shù):
from keras.utils.np_utils import to_categorical
one_hot_train_labels = to_categorical(train_labels)
one_hot_test_labels = to_categorical(test_labels)
模型搭建
使用Dense線性連接堆棧結構纯趋,每層網絡只能處理上層網絡的輸出結果憎兽。如果網絡層丟失了一些關于分類問題的信息冷离,那么下一層網絡并不能恢復這些信息:每個網絡層潛在地成為一個信息處理瓶頸。
網絡定義
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'))
關于這個網絡架構有兩點需要注意:
- 最后一層網絡神經元數(shù)目為46.意味著每個輸入樣本最終變成46維的向量纯命。輸出向量的每個數(shù)表示不同的類別西剥;
- 最后一層網絡使用softmax激活函數(shù)--網絡會輸出一個46類的概率分布。每個輸入最終都會產生一個46維的向量亿汞,每個數(shù)表示屬于該類別的概率瞭空,46個數(shù)加起來等于1.
最好的損失函數(shù)為categorical_crossentropy---衡量兩個概率分布之間的距離:網絡的輸出向量和標簽的真實分布向量疗我。通過最小化兩個分布之間的距離咆畏,訓練網絡模型,使得輸出向量盡可能與真實分布相似吴裤。
model.compile(optimizer='rmsprop',loss='categorical_crossentropy', metrics=['accuracy'])
模型驗證
在訓練數(shù)據(jù)中分出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:]
訓練20個epochs
history = model.fit(partial_x_train,partial_y_train,epochs=20,batch_size=512,validation_data=(x_val, y_val))
訓練集和驗證集的損失值變化
訓練集和驗證集的準確率變化
模型在第9次epochs之后開始過擬合。我們將epochs設置為5重新訓練麦牺,同時在測試集上測試钮蛛。
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'))
model.compile(optimizer='rmsprop',loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(partial_x_train,partial_y_train,epochs=9,batch_size=512,
validation_data=(x_val, y_val))
results = model.evaluate(x_test, one_hot_test_labels)
# [0.9565213431445807, 0.79697239536954589] 損失值,準確率
準確率達到80%.比隨機猜測好剖膳。
預測新數(shù)據(jù)
使用predict函數(shù)魏颓,產生一個46維的概率分布。在測試數(shù)據(jù)上進行預測:
predictions = model.predict(x_test)
在預測結果中概率最大的類別就是預測類:
np.argmax(predictions[0])#第一條新聞的預測類 4
另一種標簽潮秘、損失函數(shù)處理方式
直接將列表轉換成numpy數(shù)組
y_train = np.array(train_labels)
y_test = np.array(test_labels)
需要改變的是損失函數(shù)的選擇琼开。categorical_crossentropy損失函數(shù)期望標簽數(shù)據(jù)使用categorical encoding編碼方式。整數(shù)標簽枕荞,應該使用sparse_categorical_crossentropy損失函數(shù):
model.compile(optimizer='rmsprop',loss='sparse_categorical_crossentropy',metrics=['acc'])
新的損失函數(shù)在數(shù)學表示上與categorical_crossentropy損失函數(shù)相同柜候,只是接口不同。
有充分大規(guī)模中間層的重要性
因為最終分為46類躏精,中間層的神經元數(shù)目不應該小于46個渣刷。如果中間層數(shù)目小于46,有4個矗烛,將會產生信息瓶頸辅柴。
model = models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(4, activation='relu'))
model.add(layers.Dense(46, activation='softmax'))
model.compile(optimizer='rmsprop',loss='categorical_crossentropy',metrics=['accuracy'])
model.fit(partial_x_train,partial_y_train,epochs=20,batch_size=128,validation_data=(x_val, y_val))
最終訓練結果最高為71%,降低了8個百分點瞭吃。主要原始是模型試圖將大量的信息壓縮到低緯度空間中表示碌嘀,丟失了大量重要的信息。
小結
- N分類問題歪架,網絡最后Dense層神經元數(shù)目為N股冗;
- 單標簽多分類問題中,最后一層的激活函數(shù)為softmax和蚪,產生一個包含N類的概率分布止状;
- categorical crossentropy是處理單標簽多分類問題最常用的損失函數(shù)烹棉;
- 在多分類問題中有兩種標簽處理方式:
- 使用categorical encoding(one-hot)編碼,將標簽one-hot化怯疤,同時使用categorical_crossentropy作為損失函數(shù)浆洗;
- 編碼成整數(shù)向量,使用sparse_categorical_crossentropy作為損失函數(shù)集峦;
- 如果分類數(shù)目過大伏社,應該避免網絡中間層數(shù)目過小(比分類數(shù)目小--信息壓縮),產生信息瓶頸少梁。