文章代碼來源:《deep learning on keras》溉痢,非常好的一本書僻造,大家如果英語好,推薦直接閱讀該書孩饼,如果時(shí)間不夠髓削,可以看看此系列文章,文章為我自己翻譯的內(nèi)容加上自己的一些思考镀娶,水平有限蔬螟,多有不足,請(qǐng)多指正汽畴,翻譯版權(quán)所有旧巾,若有轉(zhuǎn)載,請(qǐng)先聯(lián)系本人忍些。
個(gè)人方向?yàn)閿?shù)值計(jì)算鲁猩,日后會(huì)向深度學(xué)習(xí)和計(jì)算問題的融合方面靠近,若有相近專業(yè)人士罢坝,歡迎聯(lián)系廓握。
系列文章:
一搅窿、搭建屬于你的第一個(gè)神經(jīng)網(wǎng)絡(luò)
二、訓(xùn)練完的網(wǎng)絡(luò)去哪里找
三隙券、【keras實(shí)戰(zhàn)】波士頓房?jī)r(jià)預(yù)測(cè)
四男应、keras的function API
五、keras callbacks使用
六娱仔、機(jī)器學(xué)習(xí)基礎(chǔ)Ⅰ:機(jī)器學(xué)習(xí)的四個(gè)標(biāo)簽
七沐飘、機(jī)器學(xué)習(xí)基礎(chǔ)Ⅱ:評(píng)估機(jī)器學(xué)習(xí)模型
八、機(jī)器學(xué)習(xí)基礎(chǔ)Ⅲ:數(shù)據(jù)預(yù)處理牲迫、特征工程和特征學(xué)習(xí)
九耐朴、機(jī)器學(xué)習(xí)基礎(chǔ)Ⅳ:過擬合和欠擬合
十、機(jī)器學(xué)習(xí)基礎(chǔ)Ⅴ:機(jī)器學(xué)習(xí)的一般流程十一盹憎、計(jì)算機(jī)視覺中的深度學(xué)習(xí):卷積神經(jīng)網(wǎng)絡(luò)介紹
十二筛峭、計(jì)算機(jī)視覺中的深度學(xué)習(xí):從零開始訓(xùn)練卷積網(wǎng)絡(luò)
十三、計(jì)算機(jī)視覺中的深度學(xué)習(xí):使用預(yù)訓(xùn)練網(wǎng)絡(luò)
十四陪每、計(jì)算機(jī)視覺中的神經(jīng)網(wǎng)絡(luò):可視化卷積網(wǎng)絡(luò)所學(xué)到的東西
之前mnist的例子是一個(gè)分類問題影晓,今天來講的是回歸問題,所謂回歸就是根據(jù)過去的點(diǎn)來擬合曲線檩禾,然后根據(jù)曲線來預(yù)測(cè)以后的值俯艰。
from keras.datasets import boston_housing
(train_data, train_targets), (test_data, test_targets) = boston_housing.load_data()
這個(gè)數(shù)據(jù)集和之前的mnist不同,只有506個(gè)數(shù)據(jù)锌订,而且每一個(gè)特征的取值范圍也不盡相同。
>>> train_data.shape
(404, 13)
>>> test_data.shape
(102, 13)
我們可以看到訓(xùn)練數(shù)據(jù)包含404個(gè)點(diǎn)画株,每個(gè)數(shù)據(jù)點(diǎn)包含13個(gè)特征辆飘。
這十三個(gè)特征包括:
1.人均犯罪率
2.在25000平方英尺上住房的比例
3.每個(gè)鎮(zhèn)上平均的非零售企業(yè)比例
4.Charles River dummy variable(= 1 if tract bounds river; 0 otherwise))
5.一氧化氮的濃度,單位是千萬分之一
6.每個(gè)住所的平均房間數(shù)
7.1940年以前自己修的建筑比例
8.波士頓五個(gè)就業(yè)中心的加權(quán)距離
9.徑向公路適應(yīng)性指標(biāo)
10.每10000的稅率的完全價(jià)值
11.鎮(zhèn)上的學(xué)生-老師比例
12.其中Bk是黑人比例
13.低地位人口比例
而標(biāo)簽則是有房子人的房?jī)r(jià)的中位數(shù)谓传。
數(shù)據(jù)準(zhǔn)備
mean = train_data.mean(axis=0)
train_data -= mean
std = train_data.std(axis=0)
train_data /= std
test_data -= mean
test_data /= std
有必要解釋一下axis蜈项,這個(gè)代表的是運(yùn)算的方向,我們的train_data是兩個(gè)維度的续挟,為(404,13)紧卒,由于python從0開始計(jì)數(shù),axis=0的意思就是考慮404這個(gè)維度上的數(shù)據(jù)诗祸,這里mean就是求這404個(gè)數(shù)據(jù)的均值跑芳,std則求這404個(gè)數(shù)據(jù)的標(biāo)準(zhǔn)差,然后剩下的就是減去均值除以標(biāo)準(zhǔn)差直颅,這個(gè)過程叫做歸一化博个,屬于正則化的一種,目的是防止不收斂功偿,這個(gè)之前提到過盆佣。
搭建網(wǎng)絡(luò)
由于數(shù)據(jù)量小,我們搭建的網(wǎng)絡(luò)的量級(jí)也小,才能夠防止過擬合
from keras import models
from keras import layers
def build_model():
# Because we will need to instantiate
# the same model multiple time,
# we use a function to construct it.
model = models.Sequential()
model.add(layers.Dense(64, activation='relu',
input_shape=(train_data.shape[1],)))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(1))
model.compile(optimizer='rmsprop', loss='mse', metrics=['mae'])
return model
由于我們要實(shí)例化教學(xué)共耍,這個(gè)模型將會(huì)用很多次虑灰,所以這里定義成一個(gè)函數(shù)來調(diào)用。
在這里有三點(diǎn)需要說明:
- 最后一次直接輸出了一個(gè)值痹兜,這樣就能夠預(yù)測(cè)任意范圍的值了穆咐,如果調(diào)用了什么激活函數(shù),例如sigmoid佃蚜,會(huì)導(dǎo)致最后得到的值限制在0庸娱,1之間,那么這不是我們想要的谐算。
- 這里的loss采用了mse熟尉,均方誤差,這在回歸問題中很常用洲脂。
- metrics采用mae斤儿,代表絕對(duì)誤差,即預(yù)測(cè)值和目標(biāo)值的差值的絕對(duì)值恐锦。
k重驗(yàn)證集
數(shù)據(jù)量小導(dǎo)致了我們?cè)谶M(jìn)行驗(yàn)證的時(shí)候很可能結(jié)果會(huì)依賴于我們選取的驗(yàn)證集往果,為了解決這個(gè)問題,我們就把測(cè)試集劃成幾部分一铅,這幾部分輪流當(dāng)驗(yàn)證集陕贮,分別訓(xùn)練驗(yàn)證,得到結(jié)果潘飘,最后平均一下肮之,得到的結(jié)果就更具有說服力,這就叫做k-fold卜录。
import numpy as np
k = 4
num_val_samples = len(train_data) // k
num_epochs = 100
all_scores = []
for i in range(k):
print('processing fold #', i)
# Prepare the validation data: data from partition # k
val_data = train_data[i * num_val_samples: (i + 1) * num_val_samples]
val_targets = train_targets[i * num_val_samples: (i + 1) * num_val_samples]
# Prepare the training data: data from all other partitions
partial_train_data = np.concatenate(
[train_data[:i * num_val_samples],
train_data[(i + 1) * num_val_samples:]],
axis=0)
partial_train_targets = np.concatenate(
[train_targets[:i * num_val_samples],
train_targets[(i + 1) * num_val_samples:]],
axis=0)
# Build the Keras model (already compiled)
model = build_model()
# Train the model (in silent mode, verbose=0)
model.fit(partial_train_data, partial_train_targets,
epochs=num_epochs, batch_size=1, verbose=0)
# Evaluate the model on the validation data
val_mse, val_mae = model.evaluate(val_data, val_targets, verbose=0)
all_scores.append(val_mae)
代碼本身沒什么難度戈擒,最難的可能也就是concatenate沒見過,這個(gè)就是把兩個(gè)數(shù)組連在一起艰毒。
>>> all_scores
[2.588258957792037, 3.1289568449719116, 3.1856116051248984, 3.0763342615401386]
>>> np.mean(all_scores)
2.9947904173572462
最后得到了結(jié)果筐高,預(yù)測(cè)接近于3.0
保存每一次交換訓(xùn)練的結(jié)果
把訓(xùn)練批次調(diào)到500以后查看預(yù)測(cè)均值和預(yù)測(cè)的變換趨勢(shì)
num_epochs = 500
all_mae_histories = []
for i in range(k):
print('processing fold #', i)
# Prepare the validation data: data from partition # k
val_data = train_data[i * num_val_samples: (i + 1) * num_val_samples]
val_targets = train_targets[i * num_val_samples: (i + 1) * num_val_samples]
# Prepare the training data: data from all other partitions
partial_train_data = np.concatenate(
[train_data[:i * num_val_samples],
train_data[(i + 1) * num_val_samples:]],
axis=0)
partial_train_targets = np.concatenate(
[train_targets[:i * num_val_samples],
train_targets[(i + 1) * num_val_samples:]],
axis=0)
# Build the Keras model (already compiled)
model = build_model()
# Train the model (in silent mode, verbose=0)
history = model.fit(partial_train_data, partial_train_targets,
validation_data=(val_data, val_targets),
epochs=num_epochs, batch_size=1, verbose=0)
mae_history = history.history['val_mean_absolute_error']
all_mae_histories.append(mae_history)
計(jì)算訓(xùn)練后的均值:
average_mae_history = [
np.mean([x[i] for x in all_mae_histories]) for i in range(num_epochs)]
繪出預(yù)測(cè)變化:
由于樣本數(shù)量小,造成了方差大丑瞧,波動(dòng)比較大柑土。
為了便于觀察,選取十個(gè)點(diǎn)绊汹,滑動(dòng)平均:
def smooth_curve(points, factor=0.9):
smoothed_points = []
for point in points:
if smoothed_points:
previous = smoothed_points[-1]
smoothed_points.append(previous * factor + point * (1 - factor))
else:
smoothed_points.append(point)
return smoothed_points
smooth_mae_history = smooth_curve(average_mae_history[10:])
plt.plot(range(1, len(smooth_mae_history) + 1), smooth_mae_history)
plt.xlabel('Epochs')
plt.ylabel('Validation MAE')
plt.show()
這幅圖我們能比較 清楚的看到冰单,在80epochs以后誤差又開始上升,這說明開始過擬合了灸促。
調(diào)整epochs再來一遍
# Get a fresh, compiled model.
model = build_model()
# Train it on the entirety of the data.
model.fit(train_data, train_targets,
epochs=80, batch_size=16, verbose=0)
test_mse_score, test_mae_score = model.evaluate(test_data, test_targets)
最后我們得到結(jié)果
>>> test_mae_score
2.5532484335057877