Tensorflow是Google開源的第二代用於數字計算的軟件庫。起初,它是Google大腦團隊爲了研究機器學習和神經網絡而開發的,可是後來發現這個系統足夠通用, 可以支持更加普遍的應用,就將其開源貢獻了出來。
tensorflow能夠理解爲一個深度學習框架,裏面有完整的數據流向與處理機制,同時還封裝了大量高效可用的算法與神經網絡搭建方面的函數, 能夠在此基礎之上進行深度學習的開發和研究。git
TensorFlow與CNTK、MXNET、Theano同屬於符號計算框架,容許用戶不須要使用其餘的低級語言(如Caffe中)實現的狀況下,開發出新的複雜層模型。基於圖運算是其基本特色,經過圖上的節點變量能夠控制訓練中的各個環節變量,尤爲在須要對底層操做時,TensorFlow要比其餘的框架更容易。固然也有缺點,靈活的操做會真加使用複雜度,從而增長必定的學習成本。算法
做爲主流的框架, TensorFlow生成是模型, 更加具備便捷和通用的特色, 能夠更加知足使用者的需求, TensorFlow 能夠在Mac、Linux、Windows系統上進行開發。編程
因爲TensorFlow被使用的狀況最多,因此其框架的成熟度絕對是第一。在Google的白皮書上寫道,Google內部的大量的產品幾乎都運用了TensorFlow,如搜索排序、語言識別、谷歌相冊和天然語言處理等。數組
雖然TensorFlow在大型計算機集羣的並行處理中, 運算性能僅略低於CNTK, 可是在我的機器使用的狀況下,會根據機器的配置自動選擇CPU 或者是GPU運算, 在這方面更加的友好和智能化。瀏覽器
深度學習大概的4個步驟以下
(1)準備數據
(2)搭建模型
(3)迭代訓練
(4)使用模型網絡
import tensorflow as tf import numpy as np import matplotlib.pyplot as plt # 準備數據 train_x = np.linspace(-1, 1, 100) # 在(-1, 1)之間產生100個數據 train_y = 2 * train_x + np.random.rand(*train_x.shape) * 0.5 # 加入一些噪聲 plt.plot(train_x, train_y,"ro", label="Original data") plt.savefig("Original.png") # 保存圖像 plt.legend() plt.show()
# 搭建模型 X = tf.placeholder("float") Y = tf.placeholder("float") # 定義站位符 # 模型參數 w = tf.Variable(tf.random_normal([1]), name="weight") # 定義變量 命名爲weight b = tf.Variable(tf.zeros([1]), name="baise") # 變量 b # 前向結構 z = tf.multiply(X, w) + b # 模擬 z = X * w + b # 反向優化 cost = tf.reduce_mean(tf.square(Y-z)) # 生成值與真實值的平方差 learning_rate = 0.01 # 學習率 optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(cost) # 梯度降低法
1:訓練模型session
# 初始化因此的變量 initializer = tf.global_variables_initializer() # 定義參數 train_epochs = 20 # 迭代次數 display_step = 2 # 啓動會話(Session) with tf.Session() as sess: sess.run(initializer) # 初始化全部的變量 plotdata = {"batchsize": [], "loss": []} # 存放批次值和損失值 # 向模型輸入數據 for epoch in range(train_epochs): for (x, y) in zip(train_x,train_y): sess.run(optimizer, feed_dict={X: x, Y: y}) # 向模型喂數據 if epoch % display_step == 0: loss = sess.run(cost, feed_dict={X: train_x, Y: train_y}) print("Epoch:", epoch + 1, "Cost:", loss, "W", sess.run(w), "b", sess.run(b)) if not (loss == 'NA'): plotdata["batchsize"].append(epoch) plotdata["loss"].append(loss) print("Finished!") print("cost:", sess.run(cost, feed_dict={X: train_x, Y: train_y}), "w:", sess.run(w), "b:", sess.run(b))
運行結果以下所示:
app
2:模型的可視化操做框架
def moving_average(a, w=10): if len(a) < w: return a[:] else: return [val if idx < w else sum(a[(idx-w):idx])/w for idx, val in enumerate(a)] plt.plot(train_x, train_y, "ro", label="Original data") plt.plot(train_x, sess.run(w) * train_x + sess.run(b), label="fitted line", color='g') plt.legend() plt.savefig("new_data.png") plt.show() plotdata["avgloss"] = moving_average(plotdata["loss"]) plt.figure(1) plt.subplot(211) plt.plot(plotdata["batchsize"], plotdata["avgloss"], "b--") plt.ylabel("Loss") plt.xlabel("Minibatch number") plt.title("Minibatch run vs .Train Loss") plt.savefig("Minbatch number.png") plt.show()
可視化結果以下:dom
使用sess.run來運行模型的z節點。
print("x=0.2, z=", sess.run(z, feed_dict={X: 0.2}))
程序完整代碼以下:
import tensorflow as tf import numpy as np import matplotlib.pyplot as plt # 準備數據 train_x = np.linspace(-1, 1, 100) # 在(-1, 1)之間產生100個數據 train_y = 2 * train_x + np.random.rand(*train_x.shape) * 0.5 # 加入一些噪聲 plt.plot(train_x, train_y,"ro", label="Original data") plt.savefig("Original.png") # 保存圖像 plt.legend() plt.show() # 搭建模型 X = tf.placeholder("float") Y = tf.placeholder("float") # 定義站位符 # 模型參數 w = tf.Variable(tf.random_normal([1]), name="weight") # 定義變量 命名爲weight b = tf.Variable(tf.zeros([1]), name="baise") # 變量 b # 前向結構 z = tf.multiply(X, w) + b # 模擬 z = X * w + b # 反向優化 cost = tf.reduce_mean(tf.square(Y-z)) # 生成值與真實值的平方差 learning_rate = 0.01 # 學習率 optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(cost) # 梯度降低法 def moving_average(a, w=10): if len(a) < w: return a[:] else: return [val if idx < w else sum(a[(idx-w):idx])/w for idx, val in enumerate(a)] # 初始化因此的變量 initializer = tf.global_variables_initializer() # 定義參數 train_epochs = 20 # 迭代次數 display_step = 2 # 啓動會話(Session) with tf.Session() as sess: sess.run(initializer) # 初始化全部的變量 plotdata = {"batchsize": [], "loss": []} # 存放批次值和損失值 # 向模型輸入數據 for epoch in range(train_epochs): for (x, y) in zip(train_x,train_y): sess.run(optimizer, feed_dict={X: x, Y: y}) # 向模型喂數據 if epoch % display_step == 0: loss = sess.run(cost, feed_dict={X: train_x, Y: train_y}) print("Epoch:", epoch + 1, "Cost:", loss, "W", sess.run(w), "b", sess.run(b)) if not (loss == 'NA'): plotdata["batchsize"].append(epoch) plotdata["loss"].append(loss) plt.plot(train_x, train_y, "ro", label="Original data") plt.plot(train_x, sess.run(w) * train_x + sess.run(b), label="fitted line", color='g') plt.legend() plt.savefig("new_data.png") plt.show() plotdata["avgloss"] = moving_average(plotdata["loss"]) plt.figure(1) plt.subplot(211) plt.plot(plotdata["batchsize"], plotdata["avgloss"], "b--") plt.ylabel("Loss") plt.xlabel("Minibatch number") plt.title("Minibatch run vs .Train Loss") plt.savefig("Minbatch number.png") plt.show() print("Finished!") print("cost:", sess.run(cost, feed_dict={X: train_x, Y: train_y}), "w:", sess.run(w), "b:", sess.run(b))
(1)定義TensorFlow輸入節點。
(2)定義"學習參數"的變量.
(3)定義"運算"
(4)優化函數,優化目標
(5)初始化全部的變量。
(6)迭代更新參數到最優解。
(7)測試模型。
(8)使用模型。
TensorFlow中有也下定義輸入節點的方法。
經過佔位符定義:
具體使用tf.placeholder 函數建立。
x = tf.placeholder("float")
y = tf.placeholder("float")
例如:
input_dict={
"x":tf.placeholder("float"),
"y":tf.placeholder("float")
}
直接定義就是將定義好的的pyhton變量直接放在OP節點中參與輸入運算, 將數據的變量直接放在模型中進行訓練。
也下面的代碼爲例:
import tensorflow as tf import matplotlib.pyplot as plt import numpy as np train_x = np.linspace(-1, 1, 100) train_y = 2 * train_x + np.random.rand(*train_x.shape) * 0.2 # display plt.plot(train_x, train_y, "ro", label="Original data") plt.legend() plt.show() # 模型參數 w = tf.Variable(tf.random_normal([1]), name="weight") b = tf.Variable(tf.zeros([1]), name="baise") # 向前結構 z = tf.multiply(train_x, w) + b # 變量直接在OP中參加運算
學習參數定義和輸入參數的定義很像,包括了直接定義和字典定義兩部分。這兩種都是常見的使用方式,只不過在深度神經網絡中因爲參數過多,廣泛會使用第二種狀況。
一般用tf.Variable對參數進行定義
模型參數定義 W= tf.Variable(tf.random_normal([1]),name="weight") b = tf.Variable(tf.zeros([1]), name="baise")
# 模型參數定義 paradict ={ "w": tf.Variable(tf.random_normal([1]), name="weight"), "b": tf.Variable(tf.zeros([1]), name="baise") }
定義運算的過程是創建模型的核心過程,直接決定了模型的擬合效果。
他們都是由不一樣的神經元也不一樣的組合方式組成的網絡結構。
損失函數主要計算「輸出值」與「目標值」之間的偏差,是配合反向傳播使用的,爲了在反向傳播中能夠找到最小值,要求函數必須是可導的。
有了正向結構和損失函數後, 就是經過優化函數來優化學習參數,也是在反向傳播中完成。
反向傳播過程,就是沿着正向傳播的結構向相反方向將偏差傳遞過去。
初始化經過下面的代碼實現
init = tf.global_variables_initializer() with tf.Session() as sess: sess.run(init)
在迭代訓練的環節中,都須要創建一個session來完成,經常使用的用with語法,能夠在session結束後自動關閉。
用session.run()來訓練OP,在優化操做中,只不過是訓練的是優化的OP,同時會在外層加上循環次數。
也下面示意代碼爲參考
with tf.Session() as sess: # 使用with語法 sess.run(init) for epoch in range(train_epochs): # train_epochs:迭代次數 for (x, y) in zip(train_x, train_y): sess.run(optimizer,feed_dict={X:x, Y:y})
測試模型已經不是神經網絡的核心環節了,同歸對評估節點的輸出,獲得模型準確率(或偏差率)從而獲得模型的好壞。也下面的代碼說明:
print("cost:", sess.run(cost, feed_dict={X: train_x, Y: train_y}), "w:", sess.run(w), "b:", sess.run(b)) 也能夠寫成: print("cost:",cost.eval({X:train_x, Y:train_y}))
使用模型與測試模型類似,只不過是將損失值的節點換成輸出的節點便可。
通常會把生成 的模型進行保存起來,在經過載入也有的模型進行實際的使用。
TensorFlow的運行機制屬於「定義」與「運行」相分離。從操做層面能夠分爲模型構建和模型運行。
模型構建的概念
import tensorflow as tf string = tf.constant("hello world") with tf.Session() as sess: # with print(sess.run(string)) # 或者 sess = tf.Session() print(sess.run(string)) sess.close()
定義佔位符, 使用feed機制將數據傳入,實現+,-, *,/
a = tf.placeholder(tf.float32) b = tf.placeholder(tf.float32) add = tf.add(a, b) # a+b sub = tf.subtract(a, b) # a-b mul = tf.multiply(a, b) # a*b div = tf.divide(a, b) # a/b with tf.Session() as sess: print("Add:", sess.run(add, feed_dict={a: 3.0, b: 4.0})) print("Sub:", sess.run(sub, feed_dict={a: 3.0, b: 4.0})) print("Mul:", sess.run(mul, feed_dict={a: 3.0, b: 4.0})) print("Div:", sess.run(div, feed_dict={a: 3.0, b: 4.0})) answer: Add: 7.0 Sub: -1.0 Mul: 12.0 Div: 0.75
1.建立saver
2.在session中經過saver.save 保存模型
示意代碼以下所示: saver = tf.train.Saver() with tf.Session() as sess: sess.run(tf.global_variables_initializer()) saver.save(sess, "save_path/file_name") # file_name 不存在就會自動建立
示意代碼以下所示: saver = tf.train.Saver() with tf.Session() as sess: sess.run(tf.global_variables_initializer()) saver.restore(sess, "save_path/file_name") # 會將已經保存的變量值resotre到變量中
TensorFlow提供了一個可視化的工具TensorBoard.它能夠將訓練過程當中的各類數據展現出來,包括標量(Scalars)、圖片(Image)、音頻(Audio)、計算圖(Graph)、數據分佈、直方圖(Histograms)和嵌入式向量。能夠經過網頁來觀察模型的結構和訓練過程的各個參數之間的 變化。
模型操做相關的函數
tf.summary.scalar(tags, values, collections=None, name=None)#標量的數據彙總。
tf.summary.histogram(tags,values, collections=None, name=None) # 記錄變量var的直方圖,輸出帶直方圖的彙總的protobuf。
tf.summary.image(tag, values, max_image=3, collections=None, name=None)# 圖像數據彙總,輸出protobuf。
tf.summary.merge(inputs, collections=None, name=None) # 合併因此的彙總日誌。
tf.summary.FileWriter # 建立一個summaryWriter。
class summary_write: # 將protibuf寫成文件的類。
add_summary()
add sessionlog(),
add_event()
or add_graph()
也上面的線性迴歸進行可視化操做
關鍵的代碼以下:
# 前向結構 z = tf.multiply(X, w) + b # 模擬 z = X * w + b tf.summary.histogram("z", z) # 將預測值也直方圖的形式顯示 # 反向優化 cost = tf.reduce_mean(tf.square(Y-z)) # 生成值與真實值的平方差 tf.summary.scalar("loss_functions", cost) # 也損失函數爲標量的形式顯示 with tf.Session() as sess: sess.run(initializer) # 初始化全部的變量 merged_summary_op = tf.summary.merge_all() # 合併因此的summary plotdata = {"batchsize": [], "loss": []} # 存放批次值和損失值 # 建立summary_write, 用於寫文件的操做 summary_write = tf.summary.FileWriter("F:/code_data/log/mnist_with_summaries", sess.graph) # 向模型輸入數據 for epoch in range(train_epochs): for (x, y) in zip(train_x, train_y): sess.run(optimizer, feed_dict={X: x, Y: y}) # 向模型喂數據 summary_str = sess.run(merged_summary_op, feed_dict={X: x, Y: y}) # 生成summary summary_write.add_summary(summary_str, epoch) # 將summary寫入文件
找到你的summary日誌文件夾 複製路徑:F:\code_data\log\mnist_with_summaries
在電腦上運行cmd,啓動命令行窗口
輸入:tensorboard --logdir F:\code_data\log\mnist_with_summaries
拷貝上面的地址, 在瀏覽器上打開。
import tensorflow as tf var1 = tf.Variable(1.0, name="firstval") print("var1:", var1.name) var1 = tf.Variable(2.0, name="firstval") print("var1:", var1.name) var2 = tf.Variable(3.0) print("var2:",var2.name) var2 = tf.Variable(3.0) print("var1:", var2.name) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) print("var1:", var1.eval()) print("var2:", var2.eval()) ''' answer: var1 firstval:0 var1 firstval_1:0 var2 Variable:0 var1 Variable_1:0 var1: 2.0 var2: 3.0 定義兩次的var1,內存生成了兩個var1, 名字不一樣 而對於圖來講 後面一個有效 '''
get_Variable
get_variable = tf.get_variable("firstvar", [1], initializer=tf.constant_initializer(0.3)) print(get_variable.name) get_variable = tf.get_variable("firstvar", [1], initializer=tf.constant_initializer(0.4))
會產生 Traceback (most recent call last):
使用get_variable只能定義一次指定名稱。
get_variable = tf.get_variable("firstvar", [1], initializer=tf.constant_initializer(0.3)) print(get_variable.name) get_variable = tf.get_variable("firstvar1", [1], initializer=tf.constant_initializer(0.4)) print(get_variable.name) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) print("values:", get_variable.eval()) # 0.4
將名字改爲firstval1程序正常的輸出。
import tensorflow as tf # var1 = tf.get_variable("firstvar", shape=[2], dtype=tf.float32) # var2 = tf.get_variable("firstvar", shape=[2], dtype=tf.float32) # 這樣建立var1和var2 ERROR with tf.variable_scope("test1", ): # 表示定義一個做用域 var1 = tf.get_variable("firstvar", shape=[2], dtype=tf.float32) print("var1", var1.name) with tf.variable_scope("test2", ): var2 = tf.get_variable("firstvar", shape=[2], dtype=tf.float32) print("var2:", var2.name) """ var1 test1/firstvar:0 var2: test2/firstvar:0 """ # scope的嵌套 with tf.variable_scope("test1",): var1 = tf.get_variable("firstvar", shape=[2], dtype=tf.float32) print("Var1:", var1.name) with tf.variable_scope("test2", ): var2 = tf.get_variable("firstvar", shape=[2], dtype=tf.float32) print("Var2:", var2.name) """ Var1: test1/firstvar:0 Var2: test1/test2/firstvar:0 """
代碼的相關步驟:
(1)導入MNIST數據集。
(2)分析MNIST樣本的特色定義變量。
(3)構建模型。
(4)訓練模型並輸出中間變量的參數。
(5)測試模型。
(6)保留模型。
(7)讀取模型。
示意代碼以下: import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) # 下載MNIST數據 保存在同級目錄下的MNIST_data文件夾 print("data", mnist.train.images) print("data", mnist.train.images.shape) # 55000, 784 # 定義變量 x = tf.placeholder(tf.float32, [None, 784]) # 28 * 28 y = tf.placeholder(tf.float32, [None, 10]) # 10個分類 # 定義學習參數 w = tf.Variable(tf.random_normal([784, 10])) b = tf.Variable(tf.zeros([10])) # 定義輸出節點 pred = tf.nn.softmax(tf.matmul(x, w) + b) cost = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred), reduction_indices=1)) # 損失函數 learing_rate = 0.1 # 學習率 optimizer = tf.train.GradientDescentOptimizer(learning_rate=learing_rate).minimize(cost) # 梯度降低優化器 train_ecops = 20 # 迭代次數 batch_size = 100 # 批次大小 display_step = 1 with tf.Session() as sess: sess.run(tf.global_variables_initializer()) # 變量初始化 for epoch in range(train_ecops): avg_cost = 0 total_batch = int(mnist.train.num_examples / batch_size) for i in range(total_batch): batch_xs, batch_ys = mnist.train.next_batch(batch_size) _, c = sess.run([optimizer, cost], feed_dict={x: batch_xs, y: batch_ys}) # 優化器啓動 avg_cost += (c/total_batch) # 計算平均的loss if (epoch+1) % display_step == 0: # 顯示訓練中的詳細信息 print("Epoch:", "%4d" % (epoch + 1), "cost=", "{:.9f}".format(avg_cost)) print("finished!")
訓練的結果以下所示:
# 測試模式 correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1)) # 計算準確率 accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) print("accuracy:", accuracy.eval({x: mnist.test.images, y: mnist.test.labels})) print("finished!")
# 保存模型 saver = tf.train.Saver() model_path = "F:\code_data\log\model.ckpt" save_path = saver.save(sess, model_path) print("model saveed in file %s"% save_path)
部分代碼: import pylab with tf.Session() as sess: sess.run(tf.global_variables_initializer()) saver.restore(sess, save_path=model_path) # 測試模型 correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) print("accuracy:", accuracy.eval({x: mnist.test.images, y: mnist.test.labels})) output = tf.argmax(pred, 1) batch_xs, batch_ys = mnist.train.next_batch(2) output_val, predv = sess.run([output, pred], feed_dict={x:batch_xs, y:batch_ys}) print(output_val, predv, batch_ys) im = batch_xs[0] im = im.reshape(-1, 28) pylab.imshow(im) pylab.show() im = batch_xs[1] im = im.reshape(-1, 28) pylab.imshow(im)
·····················
一個神經元是有下面幾部分組成:
單層神經網絡模型以下所示:
數據從輸入流到輸出的流向傳遞過來的, 固然,它是假設沒有一個合適的w和b的基礎上,才能夠實現對現實環境的正常的擬合,可是在實際過程當中, 咱們不知道具體的w,b是多少纔算正常。
因而加入了一個反向偏差傳遞的方法,經過反向偏差的方法來讓模自動的進行修正,最終達到一個合適的權重。
反向傳播就很明確-告訴須要將w,b調整到多少, 剛開始沒有獲得合適的權重時,正向傳播和實際的標籤是存在偏差,反向傳播就是將這個偏差傳遞給權重,讓權重適當調整一下,來達到一個合適的輸出。
### 激活函數 ###
再神經網絡的中,經常使用的激活函數有Sigmoid,Tanh,relu和swith函數。
上述講的激活函數的輸出值爲兩種(0、1,-一、 1或者0、x)等類型, 而在實際的狀況下,須要對某個問題進行多種分類,例如前面的MNIST中, 就是多分類問題, 也是運用了softmax算法。
通常的激活函數只能分類兩類, 能夠說softmax是sigmoid類函數的擴展, 表達式以下:
softmax = exp(logits)/reduce_Sum(exp(logits), dim)
把全部值的e的x次方算出來, 後求出每個值的佔比, 保證和爲1, 通常就能夠理解softmax獲得的就是機率。
描述模型預測值與真實值的差距大小。兩種常見的算法
tensorflow上面的API
1.均值平方差
MSE = tf.reduce_mean(tf.pow(tf.sub(logits, outputs), 2.0))
MSE = tf.reduce_mean(tf.square(tf.sub(logits, outputs)))
MSE = tf.reduce_mean(tf.square(logits - outputs))
Rmse = tf.sqrt(tf.reduce_mean(tf.pow(tf.sub(logits, outputs))))
mad = tf.reduce_mean(tf.complex_abs((tf.sub(logits, outputs))))
logits:表示標籤值 outputs:表示預測值
2.交叉熵
交叉熵函數有下面的幾種。
(1)sigmoid交叉熵
(2)softmax交叉熵
(3)sqarse交叉熵
(4)加權sigmoid交叉熵
Tensorflow中的損失函數
tf.nn.sigmoid_cross_entropy_with_logits(logits, targets, name=None) # 計算logits, targets之間的交叉熵。
tf.nn.softmax_cross_entropy_with_logits(logits, labels, name=None) # 計算logits和 targets的softmax之間的交叉熵 logits和target之間的維度必須相等和相同的數據類型。
tf.nn.sparse_softmax_cross_entropy_with_logits(logits, labels, name=None) # 計算logits和 labls的softmax之間的交叉熵 樣本的真實值與預測值不須要進行one_hot編碼。
tf.nn.weighted_cross_entropy_with_logits(logits, targets, pos_weight, name=None) # 在交叉熵的基礎上給第一項城上一個係數(加權),是增長或減小正樣本在計算交叉熵時的損失值。
示意代碼以下: z = tf.matmul(x, w) + b maxout = tf.reduce_mean(z, axis=1, keep_dims=True) w2 = tf.Variable(tf.truncated_normal([1, 10], stddev=0.1)) b = tf.Variable(tf.zeros([1])) pred = tf.nn.softmax(tf.matmul(maxout, w2) + b) cost = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred), reduction_indices=1)) optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(cost)
分析腫瘤是惡性仍是良性
生成樣本數據
import tensorflow as tf import numpy as np from sklearn.utils import shuffle import matplotlib.pyplot as plt def generate(sample_size, mean, cov, diff, regression): # 生成樣本數據函數 num_classes = 2 # len(diff) samples_per_class = int(sample_size / 2) X0 = np.random.multivariate_normal(mean, cov, samples_per_class) Y0 = np.zeros(samples_per_class) for ci, d in enumerate(diff): X1 = np.random.multivariate_normal(mean + d, cov, samples_per_class) Y1 = (ci + 1) * np.ones(samples_per_class) X0 = np.concatenate((X0, X1)) Y0 = np.concatenate((Y0, Y1)) if regression == False: # one-hot 0 into the vector "1 0 class_ind = [Y == class_number for class_number in range(num_classes)] Y = np.asarray(np.hstack(class_ind), dtype=np.float32) X, Y = shuffle(X0, Y0) return X, Y np.random.seed() # 生成隨機種子 num_class= 2 mean = np.random.randn(num_class) cov = np.eye(num_class) x, y = generate(1000, mean, cov, [3.0], True) colors = ['r' if l == 0 else 'b' for l in y[:]] plt.scatter(x[:, 0], x[:, 1], c=colors) plt.xlabel("Scaled age in(yrs)") plt.ylabel("Tumor size in(cm)") plt.savefig("saled.png") plt.show()
樣本可視化圖像
完整的代碼以下所示:
import tensorflow as tf import matplotlib.pyplot as plt import numpy as np from sklearn.utils import shuffle # 模擬數據點 def generate(sample_size, mean, cov, diff, regression): num_classes = 2 # len(diff) samples_per_class = int(sample_size / 2) X0 = np.random.multivariate_normal(mean, cov, samples_per_class) Y0 = np.zeros(samples_per_class) for ci, d in enumerate(diff): X1 = np.random.multivariate_normal(mean + d, cov, samples_per_class) Y1 = (ci + 1) * np.ones(samples_per_class) X0 = np.concatenate((X0, X1)) Y0 = np.concatenate((Y0, Y1)) if regression == False: # one-hot 0 into the vector "1 0 class_ind = [Y == class_number for class_number in range(num_classes)] Y = np.asarray(np.hstack(class_ind), dtype=np.float32) X, Y = shuffle(X0, Y0) return X, Y input_dim = 2 np.random.seed(10) num_classes = 2 mean = np.random.randn(num_classes) cov = np.eye(num_classes) X, Y = generate(1000, mean, cov, [3.0], True) colors = ['r' if l == 0 else 'b' for l in Y[:]] plt.scatter(X[:, 0], X[:, 1], c=colors) plt.xlabel("Scaled age (in yrs)") plt.ylabel("Tumor size (in cm)") plt.show() lab_dim = 1 # tf Graph Input input_features = tf.placeholder(tf.float32, [None, input_dim]) input_labels = tf.placeholder(tf.float32, [None, lab_dim]) # Set model weights W = tf.Variable(tf.random_normal([input_dim, lab_dim]), name="weight") b = tf.Variable(tf.zeros([lab_dim]), name="bias") output = tf.nn.sigmoid(tf.matmul(input_features, W) + b) cross_entropy = -(input_labels * tf.log(output) + (1 - input_labels) * tf.log(1 - output)) ser = tf.square(input_labels - output) loss = tf.reduce_mean(cross_entropy) err = tf.reduce_mean(ser) optimizer = tf.train.AdamOptimizer(0.04) # 儘可能用這個--收斂快,會動態調節梯度 train = optimizer.minimize(loss) # let the optimizer train maxEpochs = 50 minibatchSize = 25 # 啓動session with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for epoch in range(maxEpochs): sumerr = 0 for i in range(np.int32(len(Y) / minibatchSize)): x1 = X[i * minibatchSize:(i + 1) * minibatchSize, :] y1 = np.reshape(Y[i * minibatchSize:(i + 1) * minibatchSize], [-1, 1]) tf.reshape(y1, [-1, 1]) _, lossval, outputval, errval = sess.run([train, loss, output, err], feed_dict={input_features: x1, input_labels: y1}) sumerr = sumerr + errval print("Epoch:", '%04d' % (epoch + 1), "cost=", "{:.9f}".format(lossval), "err=", sumerr / np.int32(len(Y) / minibatchSize)) # 圖形顯示 train_X, train_Y = generate(100, mean, cov, [3.0], True) colors = ['r' if l == 0 else 'b' for l in train_Y[:]] plt.scatter(train_X[:, 0], train_X[:, 1], c=colors) # plt.scatter(train_X[:, 0], train_X[:, 1], c=train_Y) # plt.colorbar() # x1w1+x2*w2+b=0 # x2=-x1* w1/w2-b/w2 x = np.linspace(-1, 8, 200) y = -x * (sess.run(W)[0] / sess.run(W)[1]) - sess.run(b) / sess.run(W)[1] plt.plot(x, y, label='Fitted line') plt.legend() plt.savefig('line.png') plt.show()
import tensorflow as tf import numpy as np import matplotlib.pyplot as plt from sklearn.utils import shuffle from matplotlib.colors import colorConverter, ListedColormap # 對於上面的fit能夠這麼擴展變成動態的 from sklearn.preprocessing import OneHotEncoder def onehot(y,start,end): ohe = OneHotEncoder() a = np.linspace(start,end-1,end-start) b =np.reshape(a,[-1,1]).astype(np.int32) ohe.fit(b) c=ohe.transform(y).toarray() return c # def generate(sample_size, num_classes, diff,regression=False): np.random.seed(10) mean = np.random.randn(2) cov = np.eye(2) #len(diff) samples_per_class = int(sample_size/num_classes) X0 = np.random.multivariate_normal(mean, cov, samples_per_class) Y0 = np.zeros(samples_per_class) for ci, d in enumerate(diff): X1 = np.random.multivariate_normal(mean+d, cov, samples_per_class) Y1 = (ci+1)*np.ones(samples_per_class) X0 = np.concatenate((X0,X1)) Y0 = np.concatenate((Y0,Y1)) #print(X0, Y0) if regression==False: #one-hot 0 into the vector "1 0 Y0 = np.reshape(Y0,[-1,1]) #print(Y0.astype(np.int32)) Y0 = onehot(Y0.astype(np.int32),0,num_classes) #print(Y0) X, Y = shuffle(X0, Y0) #print(X, Y) return X,Y # Ensure we always get the same amount of randomness np.random.seed(10) input_dim = 2 num_classes =3 X, Y = generate(2000,num_classes, [[3.0],[3.0,0]],False) aa = [np.argmax(l) for l in Y] colors =['r' if l == 0 else 'b' if l==1 else 'y' for l in aa[:]] plt.scatter(X[:,0], X[:,1], c=colors) plt.xlabel("Scaled age (in yrs)") plt.ylabel("Tumor size (in cm)") plt.show() lab_dim = num_classes # tf Graph Input input_features = tf.placeholder(tf.float32, [None, input_dim]) input_lables = tf.placeholder(tf.float32, [None, lab_dim]) # Set model weights W = tf.Variable(tf.random_normal([input_dim,lab_dim]), name="weight") b = tf.Variable(tf.zeros([lab_dim]), name="bias") output = tf.matmul(input_features, W) + b z = tf.nn.softmax( output ) a1 = tf.argmax(tf.nn.softmax( output ), axis=1)#按行找出最大索引,生成數組 b1 = tf.argmax(input_lables, axis=1) err = tf.count_nonzero(a1-b1) # 兩個數組相減,不爲0的就是錯誤個數 cross_entropy = tf.nn.softmax_cross_entropy_with_logits( labels=input_lables,logits=output) loss = tf.reduce_mean(cross_entropy)# 對交叉熵取均值頗有必要 optimizer = tf.train.AdamOptimizer(0.04) #儘可能用這個--收斂快,會動態調節梯度 train = optimizer.minimize(loss) # let the optimizer train maxEpochs = 50 minibatchSize = 25 # 啓動session with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for epoch in range(maxEpochs): sumerr=0 for i in range(np.int32(len(Y)/minibatchSize)): x1 = X[i*minibatchSize:(i+1)*minibatchSize,:] y1 = Y[i*minibatchSize:(i+1)*minibatchSize,:] _,lossval, outputval,errval = sess.run([train,loss,output,err], feed_dict={input_features: x1, input_lables:y1}) sumerr =sumerr+(errval/minibatchSize) print ("Epoch:", '%04d' % (epoch+1), "cost=","{:.9f}".format(lossval),"err=",sumerr/(np.int32(len(Y)/minibatchSize))) train_X, train_Y = generate(200,num_classes, [[3.0],[3.0,0]],False) aa = [np.argmax(l) for l in train_Y] colors =['r' if l == 0 else 'b' if l==1 else 'y' for l in aa[:]] plt.scatter(train_X[:,0], train_X[:,1], c=colors) x = np.linspace(-1,8,200) y=-x*(sess.run(W)[0][0]/sess.run(W)[1][0])-sess.run(b)[0]/sess.run(W)[1][0] plt.plot(x,y, label='first line',lw=3) y=-x*(sess.run(W)[0][1]/sess.run(W)[1][1])-sess.run(b)[1]/sess.run(W)[1][1] plt.plot(x,y, label='second line',lw=2) y=-x*(sess.run(W)[0][2]/sess.run(W)[1][2])-sess.run(b)[2]/sess.run(W)[1][2] plt.plot(x,y, label='third line',lw=1) plt.legend() plt.show() print(sess.run(W),sess.run(b)) train_X, train_Y = generate(200,num_classes, [[3.0],[3.0,0]],False) aa = [np.argmax(l) for l in train_Y] colors =['r' if l == 0 else 'b' if l==1 else 'y' for l in aa[:]] plt.scatter(train_X[:,0], train_X[:,1], c=colors) nb_of_xs = 200 xs1 = np.linspace(-1, 8, num=nb_of_xs) xs2 = np.linspace(-1, 8, num=nb_of_xs) xx, yy = np.meshgrid(xs1, xs2) # create the grid # Initialize and fill the classification plane classification_plane = np.zeros((nb_of_xs, nb_of_xs)) for i in range(nb_of_xs): for j in range(nb_of_xs): #classification_plane[i,j] = nn_predict(xx[i,j], yy[i,j]) classification_plane[i,j] = sess.run(a1, feed_dict={input_features: [[ xx[i,j], yy[i,j] ]]} ) # Create a color map to show the classification colors of each grid point cmap = ListedColormap([ colorConverter.to_rgba('r', alpha=0.30), colorConverter.to_rgba('b', alpha=0.30), colorConverter.to_rgba('y', alpha=0.30)]) # Plot the classification plane with decision boundary and input samples plt.contourf(xx, yy, classification_plane, cmap=cmap) plt.show()
是輸入輸出層之間使用兩個隱藏層
示意代碼以下所示: import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) print("data", mnist.train.images) print("data", mnist.train.images.shape) # 55000, 7 learning_rate = 0.01 # 學習率 train_epoches = 25 display_step = 1 batch_size = 100 # 設計兩層隱藏層 n_hidden_1 = 256 # 第一個隱藏層的節點個數 n_hidden_2 = 256 # 第二個隱藏層的節點個數 n_output = 10 # 10個分類 n_input = 784 # MNIST 28 * 28 x = tf.placeholder(tf.float32, [None, n_input]) y = tf.placeholder(tf.float32, [None, n_output]) # 參數 weight ={ "w1": tf.Variable(tf.random_normal([n_input, n_hidden_1])), "w2": tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])), "w3": tf.Variable(tf.random_normal([n_hidden_2, n_output])) } baise = { "b1": tf.Variable(tf.zeros([n_hidden_1])), "b2": tf.Variable(tf.zeros(n_hidden_1)), "b3": tf.Variable(tf.zeros(n_output)) } # 定義運函數 def multilayer_perceptron(x, weight, baise): # 第一層 layer_1 = tf.add(tf.matmul(x, weight["w1"]), baise["b1"]) layer_1 = tf.nn.relu(layer_1) # 第二層 layer_2 = tf.nn.tanh(tf.add(tf.matmul(layer_1, weight["w2"]), baise["b2"])) # 輸出層 out_layer = tf.matmul(layer_2, weight["w3"]) + baise["b3"] return out_layer # 輸出值 pred = multilayer_perceptron(x, weight=weight, baise=baise) loss = tf.reduce_mean(tf.square(y-pred)) train = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss) # 會話session with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for epoch in range(train_epoches): total_batch = int(mnist.train.num_examples / batch_size) avg_cost = 0 for i in range(total_batch): train_xs, train_ys = mnist.train.next_batch(batch_size) _, c = sess.run([train, loss], feed_dict={x: train_xs, y: train_ys}) avg_cost+= (c/total_batch) if epoch % display_step == 0: print("Epoch:{:2}, cost:{:.9f}".format(epoch+1, avg_cost))
調試結果以下所示:
卷積神經網絡包括了:
卷積結構:
卷積的完整結構:
1.步長
步長的卷積操做的核心。經過部長的變化,能夠獲得不一樣類型的卷積操做,也窄卷積爲例。
根據圖中, 能夠看出大小爲5x5大小的矩陣表明圖片,每一個圖片的右側3x3矩陣表明了卷積核, 最右側的3x3矩陣代表明瞭計算完的結果 feature map。
卷積操做依然是將卷積核(filter)和對應的圖片(image)中的矩陣數據一一相乘, 在相加,第一行feature map中的第一個元素,是有image塊中前3行和前3列中的元素與filter中的元素對應相乘後相加獲得(4=1x1 + 1x0+ 1x1 +1x0 +1x0 +1x1 +0x0 +1x1 +1x0 +0x1)
步長(stride)表示卷積核在圖片是上的移動的格數。
2.窄卷積
窄卷積(valid卷積), 從字面上能夠很容易理解, 即生成feature map比原圖像小, 它的步長是可變的, 假設滑動步長爲S, 原始圖片的大小的維度是N1xN1, 那麼卷積核的大小爲N2xN2, 卷積後的圖像爲(N1-N2)/S +1x(N1-N2)/S+1
3.同卷積
同卷積(same卷積)表示卷積後的圖像尺寸和原始圖片的大小同樣大, 同卷積的步長是固定的, 滑動步長爲1. 通常操做都須要使用padding技術(外部補一圈0, 也確保生成的尺寸不變)
4.全卷積
全卷積(full卷積)也叫反捲積, 就是把原始圖像裏的每一個像素點都用卷積操做展開。
全卷積的步長也是固定的,滑動步長爲1, 假設原始圖像的維度是N1xN1,卷積核的維度是N2xN2, 卷積後圖像的大小爲:N1-N2-1 x N1+N2-1
5反向傳播
反向傳播的核心步驟:
6.多通道卷積
通道(channel),是指圖片中像素有幾個數表示的,這幾個數一指的就是色彩,好比灰度圖的通道就是1,而彩色圖通道就是3(RGB).
在卷積神經網絡裏,通道又分爲輸入通道和輸出通道。
輸入通道:就是圖像通道,如彩色圖片, 起始輸入的通道就是3, 若是有中間層的卷積,輸入通道就是上一層的輸出通道個數,計算方法,每一個輸入通道的圖片都使用同一個卷積核進行卷積操做,生成與輸出通道匹配的feature map(好比彩色通道就是3個), 而後把這幾張feature map相同的位置上的值進行相加起來, 生成一張feature map.
輸出通道:想要幾個feature map , 就放幾個卷積核,就輸出幾個通道。
池化的主要的目的就是降維, 即在保持原有的特徵的基礎上最大限度的將數租的維度變小。
池化的操做外表跟卷積很像,只是算法不一樣。
1.均值池化
就是將圖片上的對應濾波器的大小區域,對裏面的因此不爲0的像素點取均值,特徵數據會對背景信息敏感。注意的不爲0的像素點,加上0的,會讓分母增,從而使總體數據下降。
2.最大池化
最大池化就是在圖片上對應出濾波器大小的區域,將裏面的像素點取最大值,這種方式獲得的特徵數據會對紋理特徵的信息更加敏感。
3.反向傳播
對於最大池化,直接將偏差還原到對應的位置,將它用0填入,對於均值池化,則將其所有偏差填入該像素對應的池化區域。
卷積函數的API
tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=True, data_format="NHWC", dilations=[1, 1, 1, 1], name=None)
input:須要作卷積的輸入圖像(Tensor)
filter:卷積核 (Tensor)
strides:卷積時圖像每一維移動的步長。
padding定義元素邊框的與元素內容之間的空間。只要"SAME「和"VALID", 決定不一樣卷積的方式,padding爲:"SAME"表示填充到濾波器能夠達到的圖像邊緣,"VALID":表示:邊緣不填充。
return tensor
import matplotlib.pyplot as plt # plt 用於顯示圖片 import matplotlib.image as mpimg # mpimg 用於讀取圖片 import numpy as np import tensorflow as tf myimg = mpimg.imread('F:\code_data\image\image2.jpg') plt.imshow(myimg) # 顯示圖片 plt.axis('off') # 不顯示座標軸 plt.show() print(myimg.shape) full = np.reshape(myimg, [1, 640, 1024, 3]) inputfull = tf.Variable(tf.constant(1.0, shape=[1, 640, 1024, 3])) filter = tf.Variable(tf.constant([[-1.0, -1.0, -1.0], [0, 0, 0], [1.0, 1.0, 1.0], [-2.0, -2.0, -2.0], [0, 0, 0], [2.0, 2.0, 2.0], [-1.0, -1.0, -1.0], [0, 0, 0], [1.0, 1.0, 1.0]], shape=[3, 3, 3, 1])) op = tf.nn.conv2d(inputfull, filter, strides=[1, 1, 1, 1], padding='SAME') # 3個通道輸入,生成1個feature ma o = tf.cast(((op - tf.reduce_min(op)) / (tf.reduce_max(op) - tf.reduce_min(op))) * 255, tf.uint8) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) t, f = sess.run([o, filter], feed_dict={inputfull: full}) # print(f) t = np.reshape(t, [640, 1024]) plt.imshow(t, cmap='Greys_r') # 顯示圖片 plt.axis('off') # 不顯示座標軸 plt.savefig("gray.png") plt.show()
測試結果以下:
CIFAR-10數據集包含10個類的60000張32x32的彩色圖像,每一個類有6000張圖像.有50000張訓練圖像和10000張測試圖像.CIFAR-10數據集
10個分類明細及對應的部分圖片:
示意代碼以下: import tensorflow as tf import cifar10_input import numpy as np # 訓練的尺寸 # 導入模塊和數據(data) batch_size = 128 data_dir = 'F:\\tmp\cifar10_data\cifar-10-batches-bin' image_train, label_train = cifar10_input.inputs(eval_data=False, data_dir=data_dir, batch_size= batch_size) # 定義網絡結構 # 定義權值weight def weight_variable(shape): init = tf.truncated_normal(shape, stddev=0.1) return tf.Variable(init) # 定義baise def baise_variable(shape): init = tf.constant(0.1, shape=shape) return tf.Variable(init) # 定義卷積層 def conv2d(x, w): return tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding="SAME") # 定義池化層 2*2的池化層 def max_pool_2x2(x): return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], padding="SAME", strides=[1, 2, 2, 1]) # 定義平均池化層6x6 def avg_pool_6x6(x): return tf.nn.avg_pool(x, strides=[1, 6, 6, 1], ksize=[1, 6, 6, 1], padding="SAME", ) # 定義站位符 x = tf.placeholder(tf.float32, [None, 24, 24, 3]) y = tf.placeholder(tf.float32, [None, 10]) x_image = tf.reshape(x, [-1, 24, 24, 3]) w_conv1 = weight_variable([5, 5, 3, 64]) b_conv1 = baise_variable([64]) h_conv1 = tf.nn.relu(conv2d(x_image, w_conv1) + b_conv1) h_pool1 = max_pool_2x2(h_conv1) w_conv2 = weight_variable([5, 5, 64, 64]) b_conv2 = baise_variable([64]) h_conv2 = tf.nn.relu(conv2d(h_pool1, w_conv2)) + b_conv2 h_pool2 = max_pool_2x2(h_conv2) w_conv3 =weight_variable([5, 5, 64, 10]) b_conv3 = baise_variable([10]) h_conv3 = tf.nn.relu(conv2d(h_pool2, w_conv3) + b_conv3) nt_hpool3 =avg_pool_6x6(h_conv3) nt_hpool3_flat = tf.reshape(nt_hpool3, [-1, 10]) y_conv = tf.nn.softmax(nt_hpool3_flat) cross_entropy = -tf.reduce_sum(y**tf.log(y_conv)) # 損失函數 train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy) # 梯度降低法 correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y, 1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, 'float')) # 運行session進行train sess = tf.Session() sess.run(tf.global_variables_initializer()) tf.train.start_queue_runners(sess=sess) for i in range(15000): image_batch, label_batch = sess.run([image_train, label_train]) label_b = np.eye(10, dtype=float)[label_batch] train_step.run(feed_dict={x: image_batch, y:label_b}, session=sess) if i % 500 == 0: train_accuracy = accuracy.eval(feed_dict={x: image_batch, y: label_b},session = sess) print("Stop: %d, train accuracy: %g" % (i, train_accuracy))
反捲積是指, 經過測量輸出和已知的輸入進行重構未知輸入過程。
也下的圖片是參考:
https://www.jianshu.com/p/f0674e48894c
tensorflow反捲積操做
import tensorflow as tf import numpy as np img = tf.Variable(tf.constant(1.0, shape=[1, 4, 4, 1])) filter = tf.Variable(tf.constant([1.0, 0, -1, -2], shape=[2, 2, 1, 1])) conv = tf.nn.conv2d(img, filter=filter, strides=[1, 2, 2, 1], padding="SAME") conv1 = tf.nn.conv2d(img, filter=filter, strides=[1, 2, 2, 1], padding="VALID") print(conv.shape) print(conv1.shape) # 進行反捲積 contv = tf.nn.conv2d_transpose(conv, filter, [1, 4, 4, 1], [1, 2, 2, 1], padding="SAME") contv1 = tf.nn.conv2d_transpose(conv, filter, [1, 4, 4, 1], [1, 2, 2, 1], padding="VALID") with tf.Session() as sess: sess.run(tf.global_variables_initializer()) print("conv:\n", sess.run(conv)) print("filter:\n", sess.run(filter)) print("contv:\n", sess.run(contv)) print("contv1:\n", sess.run(contv1))
1.瞭解人的記憶原理
2-3歲的小孩,剛開始說話的時候,把「我要」說成「要我」, 一看見喜歡的小零食,就會對你說「要我,要我.....」
大腦受到刺激時對後續的字有預測的功能。從神經網絡的角度理解,大腦在語音模型在某一場景下必定對這兩個字進行了前後順序的區分, 好比,第一個字的"我",後面跟着我「要」,就會以爲正常,而使用「要我」 來匹配「我要」的意思, 生活中不多遇到,就以爲奇怪。
當得到「咱們找你玩遊」信息後,大腦的語言模型會之東預測後一個字爲「戲」,而不是「樂」,「泳」等字。
在上圖中,每一個字分開載開,在語言模型中就造成一個循環的神經網絡。
每個預測的結果都會放在下一個輸入裏面進行運算,與下一次生成的輸入一塊兒來生成下一次的結果。
即以下所示:
示意代碼以下所示: import copy, numpy as np np.random.seed(0) # 隨機數生成器的種子,能夠每次獲得同樣的值 # compute sigmoid nonlinearity def sigmoid(x): # 激活函數 output = 1 / (1 + np.exp(-x)) return output # convert output of sigmoid function to its derivative def sigmoid_output_to_derivative(output): # 激活函數的導數 return output * (1 - output) int2binary = {} # 整數到其二進制表示的映射 binary_dim = 8 # 暫時製做256之內的減法 ## 計算0-256的二進制表示 largest_number = pow(2, binary_dim) binary = np.unpackbits( np.array([range(largest_number)], dtype=np.uint8).T, axis=1) for i in range(largest_number): int2binary[i] = binary[i] # input variables alpha = 0.9 # 學習速率 input_dim = 2 # 輸入的維度是2 hidden_dim = 16 output_dim = 1 # 輸出維度爲1 # initialize neural network weights synapse_0 = (2 * np.random.random((input_dim, hidden_dim)) - 1) * 0.05 # 維度爲2*16, 2是輸入維度,16是隱藏層維度 synapse_1 = (2 * np.random.random((hidden_dim, output_dim)) - 1) * 0.05 synapse_h = (2 * np.random.random((hidden_dim, hidden_dim)) - 1) * 0.05 # => [-0.05, 0.05), # 用於存放反向傳播的權重更新值 synapse_0_update = np.zeros_like(synapse_0) synapse_1_update = np.zeros_like(synapse_1) synapse_h_update = np.zeros_like(synapse_h) # training for j in range(10000): # 生成一個數字a a_int = np.random.randint(largest_number) # 生成一個數字b,b的最大值取的是largest_number/2,做爲被減數,讓它小一點。 b_int = np.random.randint(largest_number / 2) # 若是生成的b大了,那麼交換一下 if a_int < b_int: tt = b_int b_int = a_int a_int = tt a = int2binary[a_int] # binary encoding b = int2binary[b_int] # binary encoding # true answer c_int = a_int - b_int c = int2binary[c_int] # 存儲神經網絡的預測值 d = np.zeros_like(c) overallError = 0 # 每次把總偏差清零 layer_2_deltas = list() # 存儲每一個時間點輸出層的偏差 layer_1_values = list() # 存儲每一個時間點隱藏層的值 layer_1_values.append(np.ones(hidden_dim) * 0.1) # 一開始沒有隱藏層,因此初始化一下原始值爲0.1 # moving along the positions in the binary encoding for position in range(binary_dim): # 循環遍歷每個二進制位 # generate input and output X = np.array([[a[binary_dim - position - 1], b[binary_dim - position - 1]]]) # 從右到左,每次去兩個輸入數字的一個bit位 y = np.array([[c[binary_dim - position - 1]]]).T # 正確答案 # hidden layer (input ~+ prev_hidden) layer_1 = sigmoid(np.dot(X, synapse_0) + np.dot(layer_1_values[-1], synapse_h)) # (輸入層 + 以前的隱藏層) -> 新的隱藏層,這是體現循環神經網絡的最核心的地方!!! # output layer (new binary representation) layer_2 = sigmoid(np.dot(layer_1, synapse_1)) # 隱藏層 * 隱藏層到輸出層的轉化矩陣synapse_1 -> 輸出層 layer_2_error = y - layer_2 # 預測偏差 layer_2_deltas.append((layer_2_error) * sigmoid_output_to_derivative(layer_2)) # 把每個時間點的偏差導數都記錄下來 overallError += np.abs(layer_2_error[0]) # 總偏差 d[binary_dim - position - 1] = np.round(layer_2[0][0]) # 記錄下每個預測bit位 # store hidden layer so we can use it in the next timestep layer_1_values.append(copy.deepcopy(layer_1)) # 記錄下隱藏層的值,在下一個時間點用 future_layer_1_delta = np.zeros(hidden_dim) # 反向傳播,從最後一個時間點到第一個時間點 for position in range(binary_dim): X = np.array([[a[position], b[position]]]) # 最後一次的兩個輸入 layer_1 = layer_1_values[-position - 1] # 當前時間點的隱藏層 prev_layer_1 = layer_1_values[-position - 2] # 前一個時間點的隱藏層 # error at output layer layer_2_delta = layer_2_deltas[-position - 1] # 當前時間點輸出層導數 # error at hidden layer # 經過後一個時間點(由於是反向傳播)的隱藏層偏差和當前時間點的輸出層偏差,計算當前時間點的隱藏層偏差 layer_1_delta = (future_layer_1_delta.dot(synapse_h.T) + layer_2_delta.dot( synapse_1.T)) * sigmoid_output_to_derivative(layer_1) # 等到完成了全部反向傳播偏差計算, 纔會更新權重矩陣,先暫時把更新矩陣存起來。 synapse_1_update += np.atleast_2d(layer_1).T.dot(layer_2_delta) synapse_h_update += np.atleast_2d(prev_layer_1).T.dot(layer_1_delta) synapse_0_update += X.T.dot(layer_1_delta) future_layer_1_delta = layer_1_delta # 完成全部反向傳播以後,更新權重矩陣。並把矩陣變量清零 synapse_0 += synapse_0_update * alpha synapse_1 += synapse_1_update * alpha synapse_h += synapse_h_update * alpha synapse_0_update *= 0 synapse_1_update *= 0 synapse_h_update *= 0 # print out progress if (j % 800 == 0): # print(synapse_0,synapse_h,synapse_1) print("總偏差:" + str(overallError)) print("Pred:" + str(d)) print("True:" + str(c)) out = 0 for index, x in enumerate(reversed(d)): out += x * pow(2, index) print(str(a_int) + " - " + str(b_int) + " = " + str(out)) print("------------")
測試部分結果以下所示:
code: import numpy as np import tensorflow as tf import matplotlib.pyplot as plt num_epochs = 5 # 初始輸入 total_series_length = 50000 # 樣本數據 truncated_backprop_length = 15 # 截取長度 state_size = 4 num_classes = 2 echo_step = 3 # 回聲序列步長 batch_size = 5 # 批次大小 num_batches = total_series_length // batch_size // truncated_backprop_length def generateData(): # 生成數據函數 x = np.array(np.random.choice(2, total_series_length, p=[0.5, 0.5])) # 在0 和1 中選擇total_series_length個數 y = np.roll(x, echo_step) # 向右循環移位【1111000】---【0001111】 y[0:echo_step] = 0 x = x.reshape((batch_size, -1)) # 5,10000 y = y.reshape((batch_size, -1)) return (x, y) batchX_placeholder = tf.placeholder(tf.float32, [batch_size, truncated_backprop_length]) batchY_placeholder = tf.placeholder(tf.int32, [batch_size, truncated_backprop_length]) init_state = tf.placeholder(tf.float32, [batch_size, state_size]) # Unpack columns inputs_series = tf.unstack(batchX_placeholder, axis=1) # truncated_backprop_length個序列 labels_series = tf.unstack(batchY_placeholder, axis=1) current_state = init_state predictions_series = [] losses = [] for current_input, labels in zip(inputs_series, labels_series): # for current_input in inputs_series: current_input = tf.reshape(current_input, [batch_size, 1]) input_and_state_concatenated = tf.concat([current_input, current_state], 1) # current_state 4 +1 # 沿着某一個軸鏈接tensor next_state = tf.contrib.layers.fully_connected(input_and_state_concatenated, state_size , activation_fn=tf.tanh) # t f.contrib.layers.fully_connection(F,num_output,activation_fn) 函數就是全連接成層,F是輸入,num_output是下一層單元的個數,activation_fn是激活函數 current_state = next_state logits = tf.contrib.layers.fully_connected(next_state, num_classes, activation_fn=None) loss = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels, logits=logits) losses.append(loss) predictions = tf.nn.softmax(logits) predictions_series.append(predictions) total_loss = tf.reduce_mean(losses) train_step = tf.train.AdagradOptimizer(0.3).minimize(total_loss) def plot(loss_list, predictions_series, batchX, batchY): plt.subplot(2, 3, 1) # cla() # Clear axis即清除當前圖形中的當前活動軸。其餘軸不受影響。 # clf() # Clear figure清除全部軸,可是窗口打開,這樣它能夠被重複使用。 # close() # Close a figure window plt.cla() plt.plot(loss_list) for batch_series_idx in range(batch_size): one_hot_output_series = np.array(predictions_series)[:, batch_series_idx, :] single_output_series = np.array([(1 if out[0] < 0.5 else 0) for out in one_hot_output_series]) plt.subplot(2, 3, batch_series_idx + 2) plt.cla() plt.axis([0, truncated_backprop_length, 0, 2]) left_offset = range(truncated_backprop_length) left_offset2 = range(echo_step, truncated_backprop_length + echo_step) label1 = "past values" label2 = "True echo values" label3 = "Predictions" plt.plot(left_offset2, batchX[batch_series_idx, :] * 0.2 + 1.5, "o--b", label=label1) plt.plot(left_offset, batchY[batch_series_idx, :] * 0.2 + 0.8, "x--b", label=label2) plt.plot(left_offset, single_output_series * 0.2 + 0.1, "o--y", label=label3) plt.legend(loc='best') plt.draw() plt.pause(0.0001) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) plt.ion() # 打開交互模式 plt.figure() plt.show() loss_list = [] for epoch_idx in range(num_epochs): x, y = generateData() _current_state = np.zeros((batch_size, state_size)) print("New data, epoch", epoch_idx) for batch_idx in range(num_batches): # 50000/ 5 /15=分紅多少段 start_idx = batch_idx * truncated_backprop_length end_idx = start_idx + truncated_backprop_length batchX = x[:, start_idx:end_idx] batchY = y[:, start_idx:end_idx] _total_loss, _train_step, _current_state, _predictions_series = sess.run( [total_loss, train_step, current_state, predictions_series], feed_dict={ batchX_placeholder: batchX, batchY_placeholder: batchY, init_state: _current_state }) loss_list.append(_total_loss) if batch_idx % 100 == 0: print("Step", batch_idx, "Loss", _total_loss) plot(loss_list, _predictions_series, batchX, batchY) plt.ioff() plt.show()
當間隔不斷增大時,RNN 會喪失學習到鏈接如此遠的信息的能力
在理論上,RNN 絕對能夠處理這樣的 長期依賴 問題。人們能夠仔細挑選參數來解決這類問題中的最初級形式,但在實踐中,RNN 確定不可以成功學習到這些知識。而LSTM並無這個問題!
Long Short Term 網絡—— 通常就叫作 LSTM ——是一種 RNN 特殊的類型,能夠學習長期依賴信息。LSTM 由Hochreiter & Schmidhuber (1997)提出,並在近期被Alex Graves進行了改良和推廣。在不少問題,LSTM 都取得至關巨大的成功,並獲得了普遍的使用。
LSTM 經過刻意的設計來避免長期依賴問題。記住長期的信息在實踐中是 LSTM 的默認行爲,而非須要付出很大代價才能得到的能力!
全部 RNN 都具備一種重複神經網絡模塊的鏈式的形式。在標準的 RNN 中,這個重複的模塊只有一個很是簡單的結構,例如一個 tanh 層
LSTM也有這樣的結構
LSTM 擁有三個門,來保護和控制細胞狀態
忘記門
該門會讀取ht−1 和xt,輸出一個在0~1之間的數值給每一個在細胞狀態ct-1中的數字。1表示「徹底保留」, 而0表示「徹底捨棄」。
輸入門
輸出門的功能有兩部分:一部分是找到那些須要更新的細胞狀態, 另外部分是把須要更新的信息更新在細胞狀態裏。
其中, tanh層就是建立一個新的細胞狀態值向量-Ct, 會被加入到狀態中。
忘記門找到須要忘記的ft後, 在於舊狀態相乘,丟棄掉須要丟棄的信息, 在將結果加上it x Ct 使細胞狀態獲取到新的信息,這樣就完成了細胞的更新。
輸出門
首先,咱們運行一個 sigmoid 層來肯定細胞狀態的哪一個部分將輸出出去。接着,咱們把細胞狀態經過 tanh 進行處理(獲得一個在 -1 到 1 之間的值)並將它和 sigmoid 門的輸出相乘,最終輸出咱們想輸出的那部分。
一種流行的LSTM變種,由Gers和Schmidhuber (2000)提出,加入了「窺視孔鏈接」(peephole connections)。這意味着門限層也將單元狀態做爲輸入。
GRU是與LSTM幾乎同樣的另外一個經常使用的網絡結構,它將忘記門和輸入門和在一個單獨的更新門中, 一樣還混合了細胞狀態和隱藏狀態及其餘的一些改動,最終的模型比LSTM模型簡單。
code: import tensorflow as tf import numpy as np import matplotlib.pyplot as plt from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) learning_rate = 0.01 n_hiddle1 = 256 n_hiddle2 = 128 n_input = 784 x = tf.placeholder("float", [None, n_input]) y = x weights ={ "encoder_h1": tf.Variable(tf.random_normal([n_input, n_hiddle1])), "encoder_h2": tf.Variable(tf.random_normal([n_hiddle1, n_hiddle2])), "decoder_h1": tf.Variable(tf.random_normal([n_hiddle2, n_hiddle1])), "decoder_h2": tf.Variable(tf.random_normal([n_hiddle1, n_input])), } baises = { "encoder_b1": tf.Variable(tf.zeros([n_hiddle1])), "encoder_b2": tf.Variable(tf.zeros([n_hiddle2])), "decoder_b1": tf.Variable(tf.zeros([n_hiddle1])), "decoder_b2": tf.Variable(tf.zeros([n_input])), } def encoder(x): layer1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights["encoder_h1"]), baises["encoder_b1"])) layer2 = tf.nn.sigmoid(tf.add(tf.matmul(layer1, weights["encoder_h2"]), baises["encoder_b2"])) return layer2 def decoder(x): layer1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights["decoder_h1"]), baises["decoder_b1"])) layer2 = tf.nn.sigmoid(tf.add(tf.matmul(layer1, weights["decoder_h2"]), baises["decoder_b2"])) return layer2 encode_out = encoder(x) pred = decoder(encode_out) print(pred.shape) cost = tf.reduce_mean(tf.pow(y-pred, 2)) optimizer = tf.train.RMSPropOptimizer(learning_rate=learning_rate).minimize(cost) train_epochs = 20 batch_size = 256 display_step = 5 with tf.Session() as sess: sess.run(tf.global_variables_initializer()) total_batch = int(mnist.train.num_examples/batch_size) for epoch in range(train_epochs): for i in range(total_batch): batch_xs, batch_ys = mnist.train.next_batch(batch_size) _, c = sess.run([optimizer, cost], feed_dict={x: batch_xs}) if epoch % display_step == 0: # 現實日誌信息 print("Epoch:", '%04d' % (epoch + 1), "cost=", "{:.9f}".format(c)) show_num = 10 reconstruction = sess.run(pred, feed_dict={x: mnist.test.images[:show_num]}) f, a = plt.subplots(2, 10, figsize=(10, 2)) for i in range(show_num): a[0][i].imshow(np.reshape(mnist.test.images[i], (28, 28))) a[1][i].imshow(np.reshape(reconstruction[i], (28, 28))) plt.draw() plt.show()