tensorflow之曲線擬合


視頻鏈接:https://morvanzhou.github.io/tutorials/machine-learning/ML-intro/

1.定義層

定義 add_layer()

from __future__ import print_function
import tensorflow as tf

def add_layer(inputs, in_size, out_size, activation_function=None):
    Weights = tf.Variable(tf.random_normal([in_size, out_size]))
    biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
    Wx_plus_b = tf.matmul(inputs, Weights) + biases
    if activation_function is None:
        outputs = Wx_plus_b
    else:
        outputs = activation_function(Wx_plus_b)
    return outputs

解釋

add_layer函數有四個形參。分別是

  1. intputs 代表輸入值,是這個神經元網絡接收的數據,比如第二層網絡的inputs就是第一層網絡的outputs

  2. in_size 代表輸入的數據有幾個特征,比如給蘋果分類的話,特征可能有 大小、顏色、品種...

  3. out_size 代表輸出幾個特征

  4. activation_function 默認為None,即 f(x) = x

2.建造神經網絡

建造神經網絡代碼


from __future__ import print_function
import tensorflow as tf
import numpy as np

def add_layer(inputs, in_size, out_size, activation_function=None):
    # add one more layer and return the output of this layer
    Weights = tf.Variable(tf.random_normal([in_size, out_size]))
    biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
    Wx_plus_b = tf.matmul(inputs, Weights) + biases
    if activation_function is None:
        outputs = Wx_plus_b
    else:
        outputs = activation_function(Wx_plus_b)
    return outputs

# Make up some real data
x_data = np.linspace(-1,1,300)[:, np.newaxis]
noise = np.random.normal(0, 0.05, x_data.shape)
y_data = np.square(x_data) - 0.5 + noise

# define placeholder for inputs to network
xs = tf.placeholder(tf.float32, [None, 1])
ys = tf.placeholder(tf.float32, [None, 1])
# add hidden layer
l1 = add_layer(xs, 1, 10, activation_function=tf.nn.relu)
# add output layer
prediction = add_layer(l1, 10, 1, activation_function=None)

# the error between prediction and real data
loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction),
                     reduction_indices=[1]))
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

# important step
# tf.initialize_all_variables() no long valid from
# 2017-03-02 if using tensorflow >= 0.12
if int((tf.__version__).split('.')[1]) < 12:
    init = tf.initialize_all_variables()
else:
    init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

for i in range(1000):
    # training
    sess.run(train_step, feed_dict={xs: x_data, ys: y_data})
    if i % 50 == 0:
        # to see the step improvement
        print(sess.run(loss, feed_dict={xs: x_data, ys: y_data}))

解釋

1. y_data = np.square(x_data) - 0.5 + noise ,可以看到樣本數據是個二次函數


2. l1 = add_layer(xs, 1, 10, activation_function=tf.nn.relu)

① 這里添加了一個神經網絡層,這一層為隱藏層(實際上這個工程一共三層),輸入數據為xs ,xs 為 若干行,一列,代表這里有若干個樣本數據,每個樣本數據提供一個特征
所以這里in_size 為 1

② 輸出10個特征,這個數值是自己添加的(你想寫成12也可以,不過要和后邊的代碼吻合),所以這里out_size 為 10

③ 第四個參數為激勵函數 , 激勵函數的作用可以打開在這里看一下:https://blog.csdn.net/tyhj_sf/article/details/79932893
文中最后也說 “這個問題目前沒有確定的方法,憑一些經驗吧。” [無奈臉] 這里使用的relu 函數

④ 這個函數返回這若干個樣本的10 個特征,賦值給l1,l1扔給后面的函數


3. prediction = add_layer(l1, 10, 1, activation_function=None) ,這就是那個后面的函數,也是添加層,這一層為輸出層。

① l1是前面函數傳遞過來的,作為本函數的輸入數據

② 這里的10 也是前邊函數輸出的10 個特征,這里作為輸入

③ 這里的1 表示最總輸出數據的列數,輸入層當時提供的每個樣本數據特征值為1個,作為預測,輸出多個特征是不合理的/莫名其妙的,所以這里的1取決於輸入樣本值的特征。

④ 激勵函數為None,即f(x) = x

這段代碼其他地方沒什么好說的

3.結果可視化

安裝matplotlib ,tkinter .

sudo pip3 install matplotlib
sudo apt-get install pyhon-tk

代碼全文

from __future__ import print_function
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

def add_layer(inputs, in_size, out_size, activation_function=None):
    Weights = tf.Variable(tf.random_normal([in_size, out_size]))
    biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
    Wx_plus_b = tf.matmul(inputs, Weights) + biases
    if activation_function is None:
        outputs = Wx_plus_b
    else:
        outputs = activation_function(Wx_plus_b)
    return outputs

# Make up some real data
x_data = np.linspace(-1, 1, 300)[:, np.newaxis]
noise = np.random.normal(0, 0.05, x_data.shape)
y_data = np.square(x_data) - 0.5 + noise

##plt.scatter(x_data, y_data)
##plt.show()

# define placeholder for inputs to network
xs = tf.placeholder(tf.float32, [None, 1])
ys = tf.placeholder(tf.float32, [None, 1])
# add hidden layer
l1 = add_layer(xs, 1, 10, activation_function=tf.nn.relu)
# add output layer
prediction = add_layer(l1, 10, 1, activation_function=None)

# the error between prediction and real data
loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys-prediction), reduction_indices=[1]))
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
# important step
sess = tf.Session()
# tf.initialize_all_variables() no long valid from
# 2017-03-02 if using tensorflow >= 0.12
if int((tf.__version__).split('.')[1]) < 12 and int((tf.__version__).split('.')[0]) < 1:
    init = tf.initialize_all_variables()
else:
    init = tf.global_variables_initializer()
sess.run(init)

# plot the real data
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.scatter(x_data, y_data)
plt.ion()
plt.show()


for i in range(1000):
    # training
    sess.run(train_step, feed_dict={xs: x_data, ys: y_data})
    if i % 50 == 0:
        # to visualize the result and improvement
        try:
            ax.lines.remove(lines[0])
        except Exception:
            pass
        prediction_value = sess.run(prediction, feed_dict={xs: x_data})
        # plot the prediction
        lines = ax.plot(x_data, prediction_value, 'r-', lw=5)
        plt.pause(1)

擬合曲線展示

解釋

  1. 程序中有兩次作圖,一次是散點的展示,用的函數是 ax.scatter(x_data, y_data) ,另一次是畫出擬合的曲線 ax.plot(x_data, prediction_value,) ,注意,這兩個函數分別對應

  2. ax.lines.remove(lines[0]) ,你和圖像的過程是逐漸向正確方向靠攏的過程,所以擬合的曲線也是動態變化的,新的曲線繪制出來的前一瞬間,需要把上一次繪制的擬合曲線刪除,就是這句代買的作用

  3. prediction_value = sess.run(prediction, feed_dict={xs: x_data}) 獲取本次最新訓練的預測結果

  4. lines = ax.plot(x_data, prediction_value, 'r-', lw=5) , 將樣本數據x,預測結果進行擬合,得到曲線圖

  5. plt.pause(1) ,圖像暫停1s ,以供程序員觀察圖像

總結

神奇的激勵函數

我用這套代碼擬合曲線 y_data = 2*x_data*np.square(x_data) - x_data - 0.5 + noise ,發現擬合的也不錯,兩個樣本差別不小的。上邊的圖像為U行,這里為N形。如下圖。

思考

這套代碼差不多是我最初接觸到的完整代碼,但是隨着看其他教程推演,第三次看這套代碼才看明白。
不能說全明白,比如

  • 問題1: 什么情況下使用什么樣的激勵函數 這個問題,就沒有答案。
  • 問題2:在這個demo中怎么叫訓練好的模型。整個擬合過程也沒有可以輸出的中間參數

這個問題已經解決了

訓練好的模型,就是輸出中間權重參數(Weights),和偏差參數(biases)

基本原理:上面提供的代碼神經網絡共三層,輸入層,隱藏層,輸出層,其中隱藏層和輸出層使用了add_layer()函數,也就是這兩層有各自的權重參數和偏差參數。因為這兩層的輸入(in_size)和輸出(out_size)不同,所以這兩層的參數的行列數(shape)也是相應不同的。

接下來我們把訓練好的參數取出來

① 添加全局變量。在add_layer 函數前邊添加

Weights = tf.Variable([-1,-1],dtype = tf.float32)
biases = tf.Variable([-1,-1],dtype = tf.float32)

Weights2 = tf.Variable([-1,-1],dtype = tf.float32)
biases2 = tf.Variable([-1,-1],dtype = tf.float32)

② 改返回,把

return outputs

改為

return outputs,Weights,biases

③ 改接收,把

l1 = add_layer(xs, 1, 10, activation_function=tf.nn.relu)
prediction = add_layer(l1, 10, 1, activation_function=None)

改為

l1,Weights,biases = add_layer(xs, 1, 10, activation_function=tf.nn.relu)
prediction,Weights2,biases2 = add_layer(l1, 10, 1, activation_function=None)

④ 在最后添加代碼打印這些參數

print("Weights")
print(Weights)
print("biases")
print(biases)
print("Weights2")
print(Weights2)
print("biases2")
print(biases2)

打印參數結果

  • 問題3:新的結果產生新的問題。在解決問題2之后,運行代碼可以得到解,但是帶有隱藏層和激勵函數的代碼每次循行之后得到的結果不同。如以上代碼,去掉noise,連續運行兩次,得到的是差別比較大的兩組解。

之后就什么心得體會或者思考的話再想着回來補充吧 😀


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM