前言
用TensorFlow做分類任務(wù),最基本的還是兩個(gè)步驟酵使,構(gòu)建計(jì)算圖和執(zhí)行計(jì)算圖荐吉。構(gòu)建計(jì)算圖中,涉及到數(shù)據(jù)的讀取口渔,變量样屠、占位符的定義,神經(jīng)網(wǎng)絡(luò)的設(shè)計(jì)缺脉,激活函數(shù)痪欲、代價(jià)函數(shù)、優(yōu)化器的定義攻礼,等把靜態(tài)的計(jì)算圖構(gòu)建之后业踢,就開始啟動(dòng)會(huì)話執(zhí)行運(yùn)算了,計(jì)算需要訓(xùn)練的節(jié)點(diǎn)礁扮,最后得到結(jié)果知举。
這里使用sklearn中的digits數(shù)據(jù)集進(jìn)行分類任務(wù),設(shè)計(jì)簡(jiǎn)單的兩層神經(jīng)網(wǎng)絡(luò)深员,并用dropout減少過(guò)擬合负蠕,最后得到性能評(píng)估。
數(shù)據(jù)預(yù)處理
讀取digits的數(shù)據(jù)很簡(jiǎn)單倦畅,首先引入sklearn相關(guān)的庫(kù)
from sklearn.datasets import load_digits
digits = load_digits()
構(gòu)建digits實(shí)例遮糖,里面data屬性存放的數(shù)據(jù)樣本,target屬性存放樣本對(duì)應(yīng)的標(biāo)簽叠赐∮耍可以觀察到各自的shape
>>> digits.data.shape
(1797, 64)
>>> digits.target.shape
(1797,)
可以看到,data是由1797個(gè)8*8的圖片組成芭概,target是對(duì)應(yīng)的label赛不。
X, y = digits.data, digits.target
這里的每個(gè)樣本對(duì)應(yīng)一個(gè)標(biāo)簽,我們可以對(duì)標(biāo)簽進(jìn)行獨(dú)熱碼解析罢洲,把它二值化踢故,這樣方便以后softmax回歸。在sklearn中惹苗,你可以選擇OneHotEncoder或者LabelBinarizer對(duì)其進(jìn)行解析殿较。這里選擇OneHotEncoder。
from sklearn.preprocessing import OneHotEncoder
y = OneHotEncoder().fit_transform(y.reshape(-1, 1)).toarray()
OneHotEncoder的輸入必須是 2-D array,而y的shape是一維向量桩蓉,所以先將其reshape淋纲,然后利用OneHotEncoder轉(zhuǎn)換,注意院究,這樣的輸出洽瞬,y最后變成了稀疏矩陣本涕,需要利用toarray再轉(zhuǎn)換成矩陣。
接下來(lái)就是對(duì)訓(xùn)練集伙窃,測(cè)試集的分割菩颖,sklearn有專門的函數(shù),test_size參數(shù)可以選擇分割的比例对供。
from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33)
構(gòu)建計(jì)算圖
網(wǎng)絡(luò)層的設(shè)計(jì)
由于這里是要使用兩層神經(jīng)網(wǎng)絡(luò)位他,可以事先預(yù)定義網(wǎng)絡(luò)的格式、輸入輸出的函數(shù)产场,然后直接調(diào)用鹅髓。傳入的參數(shù)有網(wǎng)絡(luò)層的輸入,最后通過(guò)激活函數(shù)計(jì)算輸出京景,所以要傳入激活函數(shù)窿冯,還要設(shè)計(jì)兩層神經(jīng)元的個(gè)數(shù)。
權(quán)重和偏置的定義通過(guò)tf.Variable實(shí)現(xiàn)确徙。
使用dropout來(lái)減少過(guò)擬合醒串,所以兩層神經(jīng)元使用tf.nn.dropout激活函數(shù)。
def add_layer(input, in_size, out_size, activation=None):
W = tf.Variable(tf.random_normal([in_size, out_size]), 'W')
b = tf.Variable(tf.zeros([out_size]) + 0.1, 'b')
output = tf.nn.dropout(tf.matmul(input, W) + b, keep_prob)
if activation is None:
return output
else:
return activation(output)
占位符
占位符用來(lái)定義傳遞進(jìn)來(lái)的真實(shí)的數(shù)據(jù)樣本鄙皇,不必制定初始值芜赌,這里,來(lái)定義數(shù)據(jù)樣本伴逸、數(shù)據(jù)標(biāo)簽和dropout概率缠沈。
keep_prob = tf.placeholder(tf.float32)
xs = tf.placeholder(tf.float32, [None, 64])
ys = tf.placeholder(tf.float32, [None, 10])
網(wǎng)絡(luò)層定義
這里,使用100個(gè)神經(jīng)元的第一層错蝴,激活函數(shù)使用sigmoid函數(shù)洲愤,第二層因?yàn)橐敵?到9的數(shù)字,設(shè)計(jì)10個(gè)神經(jīng)元顷锰,激活函數(shù)使用softmax函數(shù)柬赐。
l1 = add_layer(xs, 64, 100, tf.nn.tanh)
l2 = add_layer(l1, 100, 10)
代價(jià)函數(shù)與優(yōu)化器
softmax函數(shù)一般與交叉熵代價(jià)函數(shù)相配合,TensorFlow有tf.nn.softmax_cross_entropy_with_logits直接實(shí)現(xiàn)官紫,label參數(shù)傳入真實(shí)標(biāo)簽肛宋,logits參數(shù)傳入神經(jīng)層的輸出。
優(yōu)化器使用梯度下降束世,學(xué)習(xí)率設(shè)定為0.2悼吱,最后的目的就是用梯度下降使參數(shù)按照梯度下降最快的方向變化從而使代價(jià)函數(shù)局部最優(yōu)。
loss = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(labels=ys, logits=l2))
optimizer = tf.train.GradientDescentOptimizer(0.2)
train = optimizer.minimize(loss)
tensorflow的激活函數(shù)可在tensorflow.nn里面良狈,產(chǎn)生與輸入shape相同的張量。
- tf.nn.relu
- tf.nn.relu6
- tf.nn.crelu
- tf.nn.elu
- tf.nn.softplus
- tf.nn.softsign
- tf.nn.dropout
- tf.nn.bias_add
- tf.sigmoid
- tf.tanh
根據(jù)不同的模型可以選擇不同的激活函數(shù)笨枯,一般常用的是relu薪丁、sigmoid遇西、tanh
TensorFlow的優(yōu)化器也可以自行選擇,提供了計(jì)算代價(jià)的梯度一些方法严嗜。
- tf.train.Optimizer
- tf.train.GradientDescentOptimizer
- tf.train.AdadeltaOptimizer
- tf.train.AdagradOptimizer
- tf.train.AdagradDAOptimizer
- tf.train.MomentumOptimizer
- tf.train.AdamOptimizer
- tf.train.FtrlOptimizer
- tf.train.ProximalGradientDescentOptimizer
- tf.train.ProximalAdagradOptimizer
- tf.train.RMSPropOptimizer
運(yùn)行計(jì)算圖
啟動(dòng)會(huì)話粱檀,首先初始化變量,然后設(shè)置訓(xùn)練迭代1000次漫玄,最后與真實(shí)標(biāo)簽比較茄蚯,得到準(zhǔn)確率。
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
for i in range(1000):
sess.run(train, {xs: X_train, ys: y_train, keep_prob: 0.5})
#print(y_pred.shape, ...)
result = tf.equal(tf.argmax(y_test, 1), tf.argmax(l2, 1))
acc = tf.reduce_mean(tf.cast(result, tf.float32))
#print(classification_report(y_test_res, y_pred_res))
print(sess.run(acc, {xs: X_test, keep_prob: 1}))
結(jié)論
當(dāng)?shù)谝粚邮褂胹igmoid激活函數(shù)睦优,最后準(zhǔn)確率為0.875421.
當(dāng)?shù)谝粚邮褂胻anh激活函數(shù)渗常,最后準(zhǔn)確率為0.858586.
使用0.5比例的dropout和sigmoid函數(shù)時(shí),最后準(zhǔn)確率為0.927609.
附上代碼
import tensorflow as tf
from sklearn.datasets import load_digits
from sklearn.cross_validation import train_test_split
from sklearn.preprocessing import OneHotEncoder
#from sklearn.metrics import classification_report
digits = load_digits()
#print(digits.data.shape, ...)
X, y = digits.data, digits.target
y = OneHotEncoder().fit_transform(y.reshape(-1, 1)).toarray()
# y=OneHotEncoder().fit_transform(y[:,np.newaxis])
#print(y.shape, ...)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33)
def add_layer(input, in_size, out_size, activation=None):
W = tf.Variable(tf.random_normal([in_size, out_size]), 'W')
b = tf.Variable(tf.zeros([out_size]) + 0.1, 'b')
output = tf.nn.dropout(tf.matmul(input, W) + b, keep_prob)
if activation is None:
return output
else:
return activation(output)
keep_prob = tf.placeholder(tf.float32)
xs = tf.placeholder(tf.float32, [None, 64])
ys = tf.placeholder(tf.float32, [None, 10])
l1 = add_layer(xs, 64, 100, tf.nn.tanh)
l2 = add_layer(l1, 100, 10)
loss = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(labels=ys, logits=l2))
optimizer = tf.train.GradientDescentOptimizer(0.2)
train = optimizer.minimize(loss)
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
for i in range(1000):
sess.run(train, {xs: X_train, ys: y_train, keep_prob: 0.5})
#print(y_pred.shape, ...)
result = tf.equal(tf.argmax(y_test, 1), tf.argmax(l2, 1))
acc = tf.reduce_mean(tf.cast(result, tf.float32))
#print(classification_report(y_test_res, y_pred_res))
print(sess.run(acc, {xs: X_test, keep_prob: 1}))
# 第一層使用sigmoid汗盘,最后為0.875421
# 第一層使用tanh,最后為0.858586
# 使用0.5的dropout皱碘,最后為0.927609