定義一個簡單的迴歸神經網絡結構:html
結構圖以下:python
相關函數說明:git
代碼:數組
import tensorflow as tf import numpy as np import matplotlib.pyplot as plt # 建立數據訓練數據集, x_data = np.linspace(-1, 1, 500).reshape(500, 1) noise = np.random.normal(0, 0.05, [500, 1]) # 製做噪音 y_data = np.square(x_data) + 0.5 + noise # 建立佔位符用於minibatch的梯度降低訓練,建議數據類型使用tf.float3二、tf.float64等浮點型數據 x_in = tf.placeholder(tf.float32, [None, 1]) y_in = tf.placeholder(tf.float32, [None, 1]) # 定義一個添加層的函數 def add_layer(input_, in_size, out_size, activation_funtion=None): ''' :param input_: 輸入的tensor :param in_size: 輸入的維度,即上一層的神經元個數 :param out_size: 輸出的維度,即當前層的神經元個數即當前層的 :param activation_funtion: 激活函數 :return: 返回一個tensor ''' weight = tf.Variable(tf.random_normal([in_size, out_size])) # 權重,隨機的in_size*out_size大小的權重矩陣 biase = tf.Variable(tf.zeros([1, out_size]) + 0.01) # 偏置,1*out_size大小的0.01矩陣,不用0矩陣避免計算出錯 if not activation_funtion: # 根據是否有激活函數決定輸出 output = tf.matmul(input_, weight) + biase else: output = activation_funtion(tf.matmul(input_, weight) + biase) return output # 定義隱藏層,輸入爲原始數據,特徵爲1,因此輸入爲1個神經元,輸出爲4個神經元 layer1 = add_layer(x_in, 1, 4, tf.nn.relu) # 定義輸出層,輸入爲layer1返回的tensor,輸入爲4個神經元,輸出爲1個神經元,激活函數爲ReLU predict = add_layer(layer1, 4, 1) # 定義損失函數 loss = tf.reduce_mean(tf.reduce_sum(tf.square(y_in - predict), axis=[1])) # tf.reduce_sum的axis=[1]表示按列求和 # 定義訓練的優化方式爲梯度降低 train = tf.train.GradientDescentOptimizer(0.1).minimize(loss) # 學習率爲0.1 init = tf.global_variables_initializer() with tf.Session() as sess: sess.run(init) # 訓練1000次 for step in range(1000): # 執行訓練,由於有佔位符因此要傳入字典,佔位符的好處是能夠用來作minibatch訓練,這裏數據量小,直接傳入所有數據來訓練 sess.run(train, feed_dict={x_in: x_data, y_in: y_data}) # 每50步輸出一次loss if step % 49 == 0: print(sess.run(loss, feed_dict={x_in: x_data, y_in: y_data})) # 最後畫出實際的散點圖與擬合的折線圖進行對比 predict_value = sess.run(predict, feed_dict={x_in: x_data}) # 先要得到預測值 plt.figure() plt.scatter(x_data, y_data, c='r', marker='o') plt.plot(x_data, predict_value, '--', lw=2, c='b') plt.show()
數據的詳細說明請查看:tensorflow中文社區。網絡
input_data.read_data_sets(train_dir='MNIST_data',one_hot=True) :函數做用說明,讀取數據,代碼會自動下載數據(若網絡緣由可自行下載),下載的是數據文件夾,在當前工做目錄下,裏面包含訓練集mnist.train(包含特徵mnist.train.images與標籤mnist.train.labels)與測試集mnist.test(包含特徵mnist.test.images與標籤mnist.test.labels)。參數說明,train_dir:數據相對路徑,one_hot:是否爲獨熱編碼。mnist.train.next_batch。dom
mnist.train.next_batch(batch_size) :用來獲取mnist每批次的數據,每次使用會自動獲取下一批batch_size大小的數據集。機器學習
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data # 讀取數據,代碼會自動下載數據,下載的是數據文件夾,在當前工做目錄下,裏面包含訓練集與測試集,train_dir:數據路徑,one_hot:是否爲獨熱編碼。 mnist = input_data.read_data_sets(train_dir='MNIST_data', one_hot=True) # 數據較大,所以用minbatch,batch_size每一個批次的數據個數,batch_num爲批次個數 batch_size = 1000 batch_num = mnist.train.num_examples // batch_size # 建立佔位符用於minibatch的梯度降低訓練,建議數據類型使用tf.float3二、tf.float64等浮點型數據 x_in = tf.placeholder(tf.float32, [None, 784]) y_in = tf.placeholder(tf.float32, [None, 10]) # 定義一個添加層的函數 def add_layer(input_, in_size, out_size, activation_funtion=None): ''' :param input_: 輸入的tensor :param in_size: 輸入的維度,即上一層的神經元個數 :param out_size: 輸出的維度,即當前層的神經元個數即當前層的 :param activation_funtion: 激活函數 :return: 返回一個tensor ''' weight = tf.Variable(tf.random_normal([in_size, out_size])) # 權重,隨機的in_size*out_size大小的權重矩陣 biase = tf.Variable(tf.zeros([1, out_size]) + 0.01) # 偏置,1*out_size大小的0.01矩陣,不用0矩陣避免計算出錯 if not activation_funtion: # 根據是否有激活函數決定輸出 output = tf.matmul(input_, weight) + biase else: output = activation_funtion(tf.matmul(input_, weight) + biase) return output # 定義輸出層,輸入爲layer1返回的tensor,輸入爲784個神經元,輸出爲10個神經元,激活函數爲softmax。 prediction = add_layer(x_in, 784, 10) # 這個對應下一步定義交叉熵損失函數的method1,不須要激活函數softmax # 定義交叉熵損失函數,這裏用method1 # method1:用自帶的函數,這個函數會自動對prediction進行softmax操做因此不須要前面定義prediction不須要激活函數 cross_entropy = tf.reduce_sum(tf.nn.softmax_cross_entropy_with_logits(labels=y_in, logits=prediction)) # #method2:手動計算,這裏tf.clip_by_value函數的做用是爲了不輸入爲負數或者0,log函數的定義域是大於0的,不這麼作會出現LOSS=NAN且模型準確度不變的狀況,這個坑會在代碼示例後面說明。 # cross_entropy = -tf.reduce_sum(y_in * tf.log(tf.clip_by_value(prediction,1e-8,1.0))) # 定義訓練的優化方式爲梯度降低 train = tf.train.GradientDescentOptimizer(0.1).minimize(cross_entropy) # 學習率爲0.1 # 準確度,先獲得bool型的數組correct_prediction ,再計算值爲True的平均值即爲準確率 correct_prediction = tf.equal(tf.argmax(y_in, 1), tf.argmax(prediction, 1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) init = tf.global_variables_initializer() with tf.Session() as sess: sess.run(init) # 訓練20代 for epoch in range(20): # 每代對數據進行一輪minibatch for batch in range(batch_num): batch_x, batch_y = mnist.train.next_batch(batch_size) # 每一個循環讀取batch_size大小批次的數據 sess.run(train, feed_dict={x_in: batch_x, y_in: batch_y}) acc = sess.run(accuracy, feed_dict={x_in: mnist.test.images, y_in: mnist.test.labels}) # 用測試數據計算準確度 print('第%d代%d批次,準確率爲%.6f' % (epoch + 1, batch + 1, acc))
使用method1計算較差熵時,定義prediction不能有激活函數tf.nn.softmax,由於tf.nn.softmax_cross_entropy_with_logits函數會自動對prediction進行softmax處理,因此正確的代碼以下:函數
#定義輸出層 prediction = add_layer(x_in, 784, 10) #定義交叉熵 cross_entropy = tf.reduce_sum(tf.nn.softmax_cross_entropy_with_logits(labels=y_in, logits=prediction))
能夠嘗試使用method1計算交叉熵,並定義prediction的時候傳入激活函數,會發現擬合效果變差,代碼以下學習
#定義輸出層 prediction = add_layer(x_in, 784, 10, tf.nn.softmax) #定義交叉熵 cross_entropy = tf.reduce_sum(tf.nn.softmax_cross_entropy_with_logits(labels=y_in, logits=prediction))
先來看一下,當使用method2手動計算交叉熵時,不使用tf.clip_by_value時候的代碼的時候運行是什麼樣子的,代碼修改以下:測試
#method2:手動計算,這裏tf.clip_by_value函數的做用是爲了不輸入爲負數或者0,log函數的定義域是大於0的,不這麼作會出現LOSS=NAN且模型準確度不變的狀況,這個坑會在代碼示例後面說明。 cross_entropy = -tf.reduce_sum(y_in * tf.log(prediction))
運行結果爲:
C:\Users\EDZ\PycharmProjects\DY\Scripts\python.exe C:/Users/EDZ/.PyCharm2019.1/config/scratches/tf.py Extracting MNIST_data\train-images-idx3-ubyte.gz Extracting MNIST_data\train-labels-idx1-ubyte.gz Extracting MNIST_data\t10k-images-idx3-ubyte.gz Extracting MNIST_data\t10k-labels-idx1-ubyte.gz 第1代1批次,準確率爲0.098000 第1代2批次,準確率爲0.098000 第1代3批次,準確率爲0.098000 第1代4批次,準確率爲0.098000 第1代5批次,準確率爲0.098000 第1代6批次,準確率爲0.098000 第1代7批次,準確率爲0.098000
能夠看出準確率徹底沒有變化,準確率沒有變化說明cross_entropy沒有變,沒有進行訓練,因而輸出每次迭代cross_entropy的值,代碼修改以下:
# print('第%d代%d批次,準確率爲%.6f' % (epoch + 1, batch + 1, acc)) loss = sess.run(cross_entropy, feed_dict={x_in: mnist.test.images, y_in: mnist.test.labels}) print('第%d代%d批次,loss爲%.6f' % (epoch + 1, batch + 1, loss))
運行結果爲:
C:\Users\EDZ\PycharmProjects\DY\Scripts\python.exe C:/Users/EDZ/.PyCharm2019.1/config/scratches/tf.py Extracting MNIST_data\train-images-idx3-ubyte.gz Extracting MNIST_data\train-labels-idx1-ubyte.gz Extracting MNIST_data\t10k-images-idx3-ubyte.gz Extracting MNIST_data\t10k-labels-idx1-ubyte.gz 第1代1批次,loss爲nan 第1代2批次,loss爲nan 第1代3批次,loss爲nan 第1代4批次,loss爲nan 第1代5批次,loss爲nan 第1代6批次,loss爲nan 第1代7批次,loss爲nan
出現這樣的結果是由於,log函數的定義域是x>0,可是傳入的數據predicttion可能含有0或者負數,此時就會出現計算結果爲NAN的狀況,爲了不這個狀況就須要用到tf.clip_by_value函數將數據限制在0-1之間,下面是這個函數的介紹:
tf.clip_by_value(t,clip_value_min,clip_value_max,name=None)
t
: Tensor
or IndexedSlices
.clip_value_min
: A 0-D (scalar) Tensor
, or a Tensor
with the same shape as t
. The minimum value to clip by.clip_value_max
: A 0-D (scalar) Tensor
, or a Tensor
with the same shape as t
. The maximum value to clip by.name
: A name for the operation (optional).做用:截斷tensor數據的值,讓數據的值在區間 [clip_value_min , clip_value_max] 內。若tensor的值value<clip_value_min,則返回value=clip_value_min;若clip_value_min<=value<=clip_value_max,則返回value;若clip_value_max<value,則返回clip_value_max。