小白學(xué)CNN以及Keras的速成(3)
https://sherlockliao.github.io/2017/04/29/keras3/
2017 深度學(xué)習(xí)框架發(fā)展大盤點(diǎn)--迎來 PyTorch,告別 Theano
http://sh.qihoo.com/pc/2s1corcpl1y?sign=360_e39369d1
轉(zhuǎn)載自廖星宇
cs20si: tensorflow for research 學(xué)習(xí)筆記1-4
https://zhuanlan.zhihu.com/p/28924642
https://sherlockliao.github.io/2017/08/30/cs20si3/
代碼:
https://github.com/SherlockLiao/tensorflow-beginner/blob/master/lab/logistic_regression_mnist.py
cs20si: tensorflow for research 學(xué)習(xí)筆記3

4 個(gè)月前
TensorFlow中的Linear Regression
線性回歸是機(jī)器學(xué)習(xí)中非常簡(jiǎn)單的問題,我們用tensorflow實(shí)現(xiàn)一個(gè)小例子。
問題: 希望能夠找到一個(gè)城市中縱火案和盜竊案之間的關(guān)系,縱火案的數(shù)量是X,盜竊案的數(shù)量是Y,我們建設(shè)存在如下線性關(guān)系,Y = wX + b。
TensorFlow實(shí)現(xiàn)
首先定義輸入X和目標(biāo)Y的占位符(placeholder)
X=tf.placeholder(tf.float32,shape=[],name='input')Y=tf.placeholder(tf.float32,shape=[],name='label')
里面shape=[ ]表示標(biāo)量(scalar)
然后定義需要更新和學(xué)習(xí)的參數(shù)w和b
w=tf.get_variable('weight',shape=[],initializer=tf.truncated_normal_initializer())b=tf.get_variable('bias',shape=[],initializer=tf.zeros_initializer())
接著定義好模型的輸出以及誤差函數(shù),這里使用均方誤差(Y - Y_predicted)^2
Y_predicted=w*X+bloss=tf.square(Y-Y_predicted,name='loss')
然后定義好優(yōu)化函數(shù),這里使用最簡(jiǎn)單的梯度下降,這里的學(xué)習(xí)率不僅可以是常量,還可以是一個(gè)tensor
optimizer=tf.train.GradientDescentOptimizer(learning_rate=1e-3).minimize(loss)
tensorflow是如何判斷哪些參數(shù)該更新,哪些參數(shù)不更新呢?tf.Variabel(trainable=False)就表示不對(duì)該參數(shù)進(jìn)行更新,默認(rèn)下tf.Variable(trainable=True)。
然后在session中做運(yùn)算
init=tf.global_variables_initializer()withtf.Session()assess:writer=tf.summary.FileWriter('./linear_log',graph=sess.graph)sess.run(init)foriinrange(100):total_loss=0forx,yindata:_,l=sess.run([optimizer,h_loss],feed_dict={X:x,Y:y})total_loss+=lprint("Epoch {0}: {1}".format(i,total_loss/n_samples))
可視化
我們可以打開tensorboard查看我們的結(jié)構(gòu)圖如下

最后我們將數(shù)據(jù)點(diǎn)和預(yù)測(cè)的直線畫出來

如何改善模型
1. 我們可以增加維度,原始模型是Y = Xw + b,我們可以提升一維,使其變成Y = X^2 w1 + X w2 + b
2. 可以換一種loss的計(jì)算方式,比如huber loss,當(dāng)誤差比較小的時(shí)候使用均方誤差,誤差比較大的時(shí)候使用絕對(duì)值誤差

在實(shí)現(xiàn)huber loss的時(shí)候,因?yàn)閠f是以圖的形式來定義,所以不能使用邏輯語句,比如if等,我們可以使用TensorFlow中的條件判斷語句,比如tf.where、tf.case等等,huber loss的實(shí)現(xiàn)方法如下
defhuber_loss(labels,predictions,delta=1.0):residual=tf.abs(predictions-labels)condition=tf.less(residual,delta)small_res=0.5*residual**2large_res=delta*residual-0.5*delta**2returntf.where(condition,small_res,large_res)
關(guān)于Optimizer
TensorFlow會(huì)自動(dòng)求導(dǎo),然后更新參數(shù),使用一行代碼tf.train.GradientDescentOptimizer(learning_rate=1e-3).minimize(loss),下面我們將其細(xì)分開來,講一講每一步。
自動(dòng)梯度
首先優(yōu)化函數(shù)的定義就是前面一部分opt = tf.train.GradientDescentOptimizer(learning_rate),定義好優(yōu)化函數(shù)之后,可以通過grads_and_vars = opt.compute_gradients(loss, )來計(jì)算loss對(duì)于一個(gè)變量列表里面每一個(gè)變量的梯度,得到的grads_and_vars是一個(gè)list of tuples,list中的每個(gè)tuple都是由(gradient, variable)構(gòu)成的,我們可以通過get_grads_and_vars = [(gv[0], gv[1]) for gv in grads_and_vars]將其分別取出來,然后通過opt.apply_gradients(get_grads_and_vars)來更新里面的參數(shù),下面我們舉一個(gè)小例子。
importtensorflowastfx=tf.Variable(5,dtype=tf.float32)y=tf.Variable(3,dtype=tf.float32)z=x**2+x*y+3sess=tf.Session()# initialize variablesess.run(tf.global_variables_initializer())# define optimizeroptimizer=tf.train.GradientDescentOptimizer(0.1)# compute gradient z w.r.t x and ygrads_and_vars=optimizer.compute_gradients(z,[x,y])# fetch the variableget_grads_and_vars=[(gv[0],gv[1])forgvingrads_and_vars]# dz/dx = 2*x + y= 13# dz/dy = x = 5print('grads and variables')print('x: grad {}, value {}'.format(sess.run(get_grads_and_vars[0][0]),sess.run(get_grads_and_vars[0][1])))print('y: grad {}, value {}'.format(sess.run(get_grads_and_vars[1][0]),sess.run(get_grads_and_vars[1][1])))print('Before optimization')print('x: {}, y: {}'.format(sess.run(x),sess.run(y)))# optimize parametersopt=optimizer.apply_gradients(get_grads_and_vars)# x = x - 0.1 * dz/dx = 5 - 0.1 * 13 = 3.7# y = y - 0.1 * dz/dy = 3 - 0.1 * 5 = 2.5print('After optimization using learning rate 0.1')sess.run(opt)print('x: {:.3f}, y: {:.3f}'.format(sess.run(x),sess.run(y)))sess.close()
上面程序的注釋已經(jīng)解釋了所有的內(nèi)容,就不細(xì)講了,最后可以得到下面的結(jié)果。

在實(shí)際中,我們當(dāng)然不用手動(dòng)更新參數(shù),optimizer類可以幫我們自動(dòng)更新,另外還有一個(gè)函數(shù)也能夠計(jì)算梯度。
tf.gradients(ys,xs,grad_ys=None,name='gradients',colocate_gradients_with_ops=False,gate_gradients=False,aggregation_method=None)
這個(gè)函數(shù)會(huì)返回list,list的長(zhǎng)度就是xs的長(zhǎng)度,list中每個(gè)元素都是?
。
實(shí)際運(yùn)用:?這個(gè)方法對(duì)于只訓(xùn)練部分網(wǎng)絡(luò)非常有用,我們能夠使用上面的函數(shù)只對(duì)網(wǎng)絡(luò)中一部分參數(shù)求梯度,然后對(duì)他們進(jìn)行梯度的更新。
優(yōu)化函數(shù)類型
隨機(jī)梯度下降(GradientDescentOptimizer)僅僅只是tensorflow中一個(gè)小的更新方法,下面是tensorflow目前支持的更新方法的總結(jié)
tf.train.GradientDescentOptimizertf.train.AdadeltaOptimizertf.train.AdagradOptimizertf.train.AdagradDAOptimizertf.train.MomentumOptimizertf.train.AdamOptimizertf.train.FtrlOptimizertf.train.ProximalGradientDescentOptimizertf.train.ProximalAdagradOptimizertf.train.RMSPropOptimizer
這個(gè)博客對(duì)上面的方法都做了介紹,感興趣的同學(xué)可以去看看,另外cs231n和coursera的神經(jīng)網(wǎng)絡(luò)課程也對(duì)各種優(yōu)化算法做了介紹。
TensorFlow 中的Logistic Regression
我們使用簡(jiǎn)單的logistic regression來解決分類問題,使用MNIST手寫字體,我們的模型公式如下
TensorFlow實(shí)現(xiàn)
TF Learn中內(nèi)置了一個(gè)腳本可以讀取MNIST數(shù)據(jù)集
fromtensorflow.examples.tutorials.mnistimportinput_datamnist=input_data.read_data_sets('./data/mnist',one_hot=True)
接著定義占位符(placeholder)和權(quán)重參數(shù)
x=tf.placeholder(tf.float32,shape=[None,784],name='image')y=tf.placeholder(tf.int32,shape=[None,10],name='label')w=tf.get_variable('weight',shape=[784,10],initializer=tf.truncated_normal_initializer())b=tf.get_variable('bias',shape=[10],initializer=tf.zeros_initializer())
輸入數(shù)據(jù)的shape=[None, 784]表示第一維接受任何長(zhǎng)度的輸入,第二維等于784是因?yàn)?8x28=784。權(quán)重w使用均值為0,方差為1的正態(tài)分布,偏置b初始化為0。
然后定義預(yù)測(cè)結(jié)果、loss和優(yōu)化函數(shù)
logits=tf.matmul(x,w)+bentropy=tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=logits)loss=tf.reduce_mean(entropy,axis=0)optimizer=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)
使用tf.matmul做矩陣乘法,然后使用分類問題的loss函數(shù)交叉熵,最后將一個(gè)batch中的loss求均值,對(duì)其使用隨機(jī)梯度下降法。
因?yàn)閿?shù)據(jù)集中有測(cè)試集,所以可以在測(cè)試集上驗(yàn)證其準(zhǔn)確率
preds=tf.nn.softmax(logits)correct_preds=tf.equal(tf.argmax(preds,1),tf.argmax(y,1))accuracy=tf.reduce_sum(tf.cast(correct_preds,tf.float32),axis=0)
首先對(duì)輸出結(jié)果進(jìn)行softmax得到概率分布,然后使用tf.argmax得到預(yù)測(cè)的label,使用tf.equal得到預(yù)測(cè)的label和實(shí)際的label相同的個(gè)數(shù),這是一個(gè)長(zhǎng)為batch的0-1向量,然后使用tf.reduce_sum得到正確的總數(shù)。
最后在session中運(yùn)算,這個(gè)過程就不再贅述。
### 結(jié)果與可視化
最后可以得到訓(xùn)練集的loss的驗(yàn)證集準(zhǔn)確率如下

可以發(fā)現(xiàn)經(jīng)過10 epochs,驗(yàn)證集能夠?qū)崿F(xiàn)74%的準(zhǔn)確率。同時(shí),我們還能夠得到tensorboard可視化如下。

這看著是有點(diǎn)混亂的,所以下一次課會(huì)講一下如何結(jié)構(gòu)化我們的模型。
本文的全部代碼都在github
歡迎訪問我的博客
歡迎查看我的知乎專欄深度煉丹