用numpy搭建两层神经网络进行图片分类
本实验所使用的数据集为吴恩达老师深度学习课后作业的【识别猫】数据集,训练集209张64x64图片,测试集50张64x64图片。手推前向后向计算公式,并用代码实现,加深对神经网络的理解。
数据预处理:
def dataprogress():
"""数据预处理"""
trainSet_x,trainSet_y,testSet_x,testSet_y,classes = load_dataset()
trainX_trans = trainSet_x.reshape((trainSet_x.shape[0],-1)).T
testX_trans = testSet_x.reshape((testSet_x.shape[0],-1)).T
trainX = trainX_trans / 255.0
testX = testX_trans / 255.0
return trainX,trainSet_y,testX,testSet_y,classes
网络结构如下:
旨在搭建一个两层神经网络,其中隐藏层神经元个数可选。
在本实验中输入单个X维度为(64x64x3,1)输出维度为(1,1)
损失函数为:
E i n = 1 N L ( y , y h a t ) = 1 N ( − y l o g ( y h a t ) − ( 1 − y ) l o g ( 1 − y h a t ) ) {E_{in}} = \frac{1}{N}L(y,yhat) = \frac{1}{N}( - ylog(yhat) - (1 - y)log(1 - yhat)) Ein=N1L(y,yhat)=N1(−ylog(yhat)−(1−y)log(1−yhat))
在式中 y和yhat都是矩阵,大小为(1,N)
代码实现:
def cross_entropy_error(y,yhat,N):
"""
#交叉熵损失
#Y和A的维度要相同
"""
assert(y.shape == yhat.shape)
cost = (-1/N)*(np.dot(y,np.log(yhat.T)) + np.dot((1-y),np.log((1-yhat).T)))
return cost
激活函数,隐藏层用tanh,输出层用sigmoid
代码实现:
def tanh(x):
s = (np.exp(x) - np.exp(-x)) / \
(np.exp(x) + np.exp(-x))
return s
def sigmoid(x):
return 1 / (1 + np.exp(-x))
首先定义网络结构和初始化网络参数,必须要搞清楚参数的大小,在本次实验中,W1大小为(n_h,n_x),b1 (n_h,1),W2 (n_y,n_h),b2 (n_y,1),
其中n_x :输入层节点数,
n_y :输出层节点数目,
n_h :隐藏层节点数目。
代码实现:
def layer_size(dataX,dataY,h):
"""定义网络结构"""
n_x = dataX.shape[0] #输入层节点数
n_y = dataY.shape[0] #输出层节点数目
n_h = h #隐藏层节点数目
return n_x,n_y,n_h
def initParameters(n_x,n_y,n_h):
"""初始化网络参数,n_h默认为4"""
W_1 = np.random.randn(n_h,n_x)*0.01
b_1 = np.zeros((n_h,1))
W_2 = np.random.randn(n_y,n_h)*0.01
b_2 = np.zeros((n_y,1))
return W_1,W_2,b_1,b_2
前向计算过程
Z [ 1 ] = W [ 1 ] ∗ X + b [ 1 ] {
{\text{Z}}^{[1]}} = {W^{[1]}}*X + {b^{[1]}} Z[1]=W[1]∗X+b[1]
a [ 1 ] = tanh ( Z [ 1 ] ) {a^{[1]}} = \tanh ({
{\text{Z}}^{[1]}}) a[1]=tanh(Z[1])
Z [ 2 ] = W [ 2 ] ∗ a [ 1 ] + b [ 2 ] {
{\text{Z}}^{[2]}} = {W^{[2]}}*{a^{[1]}} + {b^{[2]}} Z[2]=W[2]∗a[1]+b