一、感知機
感知機(perceptron)由美國學(xué)者Frank Rosenblatt在1957年提出的。
1、感知機的定義
接收多個輸入信號,輸出一個信號。
感知機與神經(jīng)元(節(jié)點)的區(qū)別:
感知機由神經(jīng)元構(gòu)成。
感知機的多個輸入信號都有各自的權(quán)重,權(quán)重發(fā)揮控制各個信號的重要性的作用。
2、簡單邏輯電路
與門:兩個輸入均為1時輸出1,其他輸出0
與非門:兩個輸入均為1時輸出0,其他輸出1
異或門:兩個輸入信號不相同時,輸出1,其他輸出0
權(quán)重w1,w2是控制輸入信號的重要性的參數(shù)
偏置是調(diào)整整個神經(jīng)元被激活的容易程度的參數(shù)。如b=-20.0,則輸入信號的加權(quán)總和必須超過20.0,神經(jīng)元才會被激活。
import numpy as np
def AND(x1,x2):
x = np.array([x1,x2])
w = np.array([0.5,0.5])
b = -0.7
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1
print(AND(0,0))
print(AND(1,0))
print(AND(0,1))
print(AND(1,1))
用單層感知機無法實現(xiàn)異或門。
使用與門、與非門、或門實現(xiàn)異或門。與門、或門是單層感知機,異或門是2層感知機。
import numpy as np
def AND(x1,x2):
x = np.array([x1,x2])
w = np.array([0.5,0.5])
b = -0.7
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1
def OR(x1,x2):
x = np.array([x1,x2])
w = np.array([0.5,0.5])
b = -0.2
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1
def NAND(x1,x2):
x = np.array([x1,x2])
w = np.array([-0.5,-0.5])
b = 0.7
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1
def XOR(x1,x2):
s1 = NAND(x1,x2)
s2 = OR(x1,x2)
y = AND(s1,s2)
return y
print(XOR(0,0))
print(XOR(1,0))
print(XOR(0,1))
print(XOR(1,1))
二、神經(jīng)網(wǎng)絡(luò)
神經(jīng)網(wǎng)絡(luò)由輸入層、輸出層、中間層(隱藏層)組成。有2層包含權(quán)重的,稱為2層網(wǎng)絡(luò)。
激活函數(shù):將輸入信號的總和轉(zhuǎn)換為輸出信號。感知機和神經(jīng)網(wǎng)絡(luò)的主要區(qū)別就在激活函數(shù)上。
1、階躍函數(shù)
def step_function(x):
if x > 0:
return 1
else:
return 0
用numpy實現(xiàn)階躍函數(shù)
x = np.array([-1.0,1.0,2.0])
y = x > 0
y = y.astype(np.int)
2、sigmoid函數(shù)實現(xiàn)
import numpy as np
import matplotlib.pyplot as plt
def sigmoid(x):
return 1/(1+np.exp(-x))
def step_function(x):
return np.array(x>0,dtype=np.int)
x = np.arange(-5.0,5.0,0.1)
y1 = sigmoid(x)
y2 = step_function(x)
plt.plot(x,y1,label="sigmoid")
plt.plot(x,y2,linestyle="--",label="階躍函數(shù)")
plt.ylim(-0.1,1.1)
plt.show()

神經(jīng)網(wǎng)絡(luò)的激活函數(shù)必須使用非線性函數(shù)。原因1:線性函數(shù)使加深網(wǎng)絡(luò)層數(shù)無意義,多層神經(jīng)網(wǎng)絡(luò),總能找到與之等效的無隱藏層神經(jīng)網(wǎng)絡(luò)。
3、ReLU函數(shù)
def relu(x):
return np.maximum(0,x)
4、內(nèi)積
import numpy as np
X = np.array([1,2])
W = np.array([[1,3,5],[2,4,6]])
Y = np.dot(X,W)
print(Y)
5、符號定義
(1)代表第1層權(quán)重,2代表前一層的第2個神經(jīng)元,1代表后1層的第1個神經(jīng)元。
用公式表示神經(jīng)網(wǎng)絡(luò)
第一層使用矩陣乘法的加權(quán)和表示:
兩層神經(jīng)網(wǎng)絡(luò)的代碼實現(xiàn)
import numpy as np
from deeplearning.sigmoid import *
def init_network():
network = {}
network['W1'] = np.array([[0.1,0.3,0.5],[0.2,0.4,0.6]])
network['b1'] = np.array([0.1,0.2,0.3])
network['W2'] = np.array([[0.1,0.4],[0.2,0.5],[0.3,0.6]])
network['b2'] = np.array([0.1,0.2])
network['W3'] = np.array([[0.1,0.3],[0.2,0.4]])
network['b3'] = np.array([0.1,0.2])
return network
def identity_function(x):
return x
def forward(network,x):
W1,W2,W3 = network['W1'],network['W2'],network['W3']
b1,b2,b3 = network['b1'],network['b2'],network['b3']
a1 = np.dot(x,W1)+b1
z1 = sigmoid(a1)
a2 = np.dot(z1, W2) + b2
z2 = sigmoid(a2)
a3 = np.dot(z2, W3) + b3
y = identity_function(a3)
return y
network = init_network()
x = np.array([1.0,0.5])
y = forward(network,x)
print(y)
機器學(xué)習(xí)的問題大致分為兩類:分類、回歸。分類使用softmax函數(shù),回歸用恒等函數(shù)。為什么分類問題會用softmax,因為softmax函數(shù)的特征,就是輸出的總和為1,選中其中概率最高的作為分類結(jié)果。
實現(xiàn)softmax函數(shù)
def softmax(a):
c = np.max(a)
exp_a = np.exp(a-c)
sum_exp_a = np.sum(exp_a)
y = exp_a / sum_exp_a
return y
將數(shù)據(jù)限定到某個范圍內(nèi)的處理,稱作正規(guī)化。
三、神經(jīng)網(wǎng)絡(luò)的學(xué)習(xí)
神經(jīng)網(wǎng)絡(luò)的特征就是可以從數(shù)據(jù)中學(xué)習(xí)。數(shù)據(jù)是機器學(xué)習(xí)的核心。
實際的神經(jīng)網(wǎng)絡(luò)中國,參數(shù)的數(shù)量成千上萬。
如何識別手寫5的數(shù)字?從圖像中提取特征量,學(xué)習(xí)特征量的模式,特征量指可以從輸入數(shù)據(jù)中準(zhǔn)確提取本質(zhì)數(shù)據(jù)的轉(zhuǎn)換器。
機器學(xué)習(xí),特征量由人工設(shè)計。
神經(jīng)網(wǎng)絡(luò),重要的特征量都是由機器學(xué)習(xí)的。
泛化能力,處理未被觀察過的數(shù)據(jù)的能力。獲得泛化能力是機器學(xué)習(xí)的終極目標(biāo)。避免過擬合是機器學(xué)習(xí)的一個重要課題。
神經(jīng)網(wǎng)絡(luò)中用于表示學(xué)習(xí)擬合程度指標(biāo)是,損失函數(shù)。
損失函數(shù):均方誤差
表示神經(jīng)網(wǎng)絡(luò)的輸出,
表示進度數(shù)據(jù)
均方誤差實現(xiàn)
def mean_squared_error(y,t):
return 0.5 * np.sum((y-t)**2)
交叉熵誤差
神經(jīng)網(wǎng)絡(luò)學(xué)習(xí)中,不能用識別精度作為指標(biāo)的原因是,參數(shù)的導(dǎo)數(shù)在絕大多數(shù)地方會變?yōu)?。調(diào)整參數(shù),變化是不連續(xù)的、離散的值。
為什么不能用階躍函數(shù)作為激活函數(shù),原因就是階躍函數(shù)不平滑,不能做到連續(xù)的微調(diào)。sigmoid的導(dǎo)數(shù)則是連續(xù)變化的。
導(dǎo)數(shù)實現(xiàn)
def function_1(x):
return 0.01*x**2 + 0.1*x
y = numerical_diff(function_1,5)
print(y)
機器學(xué)習(xí)的主要任務(wù)是在學(xué)習(xí)時,尋找最優(yōu)參數(shù)。
梯度下降實現(xiàn)
def gradient_descent(f, init_x, lr=0.01, step_num=100):
x = init_x
x_history = []
for i in range(step_num):
x_history.append( x.copy() )
grad = numerical_gradient(f, x)
x -= lr * grad
return x, np.array(x_history)
超參數(shù):學(xué)習(xí)率等參數(shù),由人工設(shè)定。
極小值,是某個范圍內(nèi)的最小值。
鞍點:某個方向看是最小值,從另一個方向看是最大值的點。