1.2 如何看待與理解神經網路
很多書本上都是以神經作為例子的,從60年代開始,到解決抑或問題問題,再到後來深度神經網路。歷史沿革來說經歷了將近六十年的發展,其中有八、九十年代的低潮,也有高潮。
其實說白了就是發明了好多亂七八糟的名詞之後開始有了比較大的發展的。
那麼接著上一章的東西開始,這次將整個問題簡化成一個一維的問題,也就是給定一個x有個函數將其轉化為y=f(x),那麼我們如何去獲取這個函數。這是一個純一維問題,但是整個TensorFlow的程序依然比較長:
#program1.2.1.pynimport tensorflow as tfnimport numpy as npnn#用於產生數據類nclass GenData():n def __init__(self,shape):n self.shape=shapen def Func(self,x):n x=x[0]n #數據產生依據於f(x)=0.5x+0.1n return [0.5*x+0.1]n def GenWave(self):n self.data=np.random.random(self.shape)*0.2n self.outdata=np.array(list(map(self.Func,self.data)))n return self.data,self.outdatan#為輸入的數據建立佔位符nx = tf.placeholder(tf.float32, [None,1])ny = tf.placeholder(tf.float32, [None,1])nn#整個函數的意思就是假設這是一個一維的函數f(x)=Wx+b,其中Wb都是未知數。nW = tf.Variable(tf.ones([1.,1.]))nb = tf.Variable(tf.ones([1.]))nresult =tf.matmul(x, W) + b)n#依然使得產生的result與實際的y之間最小,並運用迭代的方式取得值。nce = tf.reduce_mean(tf.square(result-y))ntrain_step = tf.train.AdamOptimizer(1e-2).minimize(ce)n#建立互動式的session,與Session()的意思一致nsess = tf.InteractiveSession()ntf.global_variables_initializer().run()ndataGenerator=GenData([50,1])n#訓練開始nfor _ in range(10000):n dt,odt=dataGenerator.GenWave()n sess.run(train_step, feed_dict={x: dt, y: odt})n#用於獲取訓練後的結果ndt,odt=dataGenerator.GenWave()nrdt=sess.run(result,feed_dict={x: dt, y: odt})n#輸出W和b的值nprint("W and b is : %f,%f"%(sess.run(W.value()),sess.run(b.value())))n#繪圖過程nimport matplotlib.pyplot as pltnimport matplotlib as mplnmpl.style.use(seaborn-darkgrid)n#擬合生成數據ncof = np.polyfit(np.reshape(dt,[-1]),np.reshape(rdt,[-1]),1) np=np.poly1d(cof)nplt.figure(1)nplt.scatter(np.reshape(dt,[-1]),np.reshape(odt,[-1]),marker=+)nplt.scatter(np.reshape(dt,[-1]),np.reshape(rdt,[-1]),marker=o)nplt.text(0,0.1,$f(x)=%f+%fx$%(cof[1],cof[0]))nx=np.linspace(0,1,100)nplt.plot(x,p(x),lw=2)nplt.show()n
很快就可以看到圖形的結果了:
完美匹配,此時的W和b分別為
W and b is : 0.500000,0.100000
可以說我們假設x所經歷的運算中:
result =tf.matmul(x, W) + b)n
就可以預見是這個結果,因為W和b在這種情況下是唯一的。而神經網路總是會匹配最佳的結果(姑且這麼認為)
但問題來了,一旦我們變換一個函數形式,那麼所得的結果就可能並非這麼完美比如將函數假設為
依然按照上面的方式得到的結果如下:
『+』號是原始數據,點是處理後數據,由結果可見通過上面的過程大致擬合了一條直線,而這個結果依然是可以預知的,只是並非那麼完美。因為曲線是非線性的。
此時再加入一個常用的sigmoid函數,這個函數大致長成這樣:
經過sigmoid後的result程序中變成這樣:result =tf.nn.sigmoid(tf.matmul(x, W) + b)n
擬合的結果變成:
W and b is : 6.341095,-2.216240
它利用了sigmoid本身曲線的形狀去模擬了二次函數,這是個很聰明的策略。這裡大致可以算是神經網路非線性問題的一個開端,再之後我們可以看到sigmoid是有最大值1 的,那麼擔心的問題產生了,如果接近1或者大於1的情況會是何種的擬合結果?
這是一個比較有代表性的問題:
可以看到,接近或者大於1 的情況下擬合情況很糟,而輸出的result顯示出了明顯的sigmoid的形狀,解決這個問題呢,之後的方法都是將所得結果歸一化,也就是除以最大值,但是現在的問題是比較簡單的,所以可以用一個係數去解決:
amp=tf.Variable(tf.ones([1.]))nresult=result*ampn
這裡amp的作用就是將y做一個伸縮的變換,至於具體伸縮多少,讓機器去迭代選取一個最佳的值,而此時:
W and b is : 2.287071,-3.683634
可以看到b是一個更小的值,也就是說程序選擇了sigmoid中更平滑的一段,因為坐標要進行伸縮,而所得的圖形結果如下:
可以看到擬合結果大大改善,但是在數值比較小的地方依然不是很完美,當然用其他激活函數去做的話所得結果如下:
總結
至此理解方式來說用函數擬合的方式去理解是可行的,relu、sigmoid等一系列函數的引入使得整個神經網路可以模擬的函數增多,但是同樣可以看到這部分是多解的,而神經網路迭代只是選取了一個他認為最合理的參數,函數的連續、可微性是一個比較重要的概念,它使得我們可以去理解神經網路的基礎的數學表象。同樣的連續可微使得神經網路得到了一定的泛化能力,也就是函數延伸出去的部分,但是可以看到這種泛化是有限度的,在顯著超出範圍的數據點是無法得到準確參數的。
那麼接下來介紹的部分我想應該用c和標準庫去實現上面的過程吧。
推薦閱讀:
※《Learning to Rank using Gradient Descent》
※機器學習-異常檢測演算法(三):Principal Component Analysis
※logistic regression
※通俗講解維特比演算法
※機器學習------令人頭疼的正則化項
TAG:神经网络 | 机器学习 | TensorFlow |