参考书:深度学习入门:基于Python的理论与实现
两层神经网络代码中,有五个方法:
1.初始化方法(__init__
)
2.预测/推理函数(predict
)
3.损失函数(loss
)
4.计算推理精度的函数(accuracy
)
5.计算各参数梯度的函数(numerical_gradient
)
import sys
import os
sys.path.append(os.pardir) # 为了导入父目录的文件而进行的设定
from common.functions import *
from common.gradient import numerical_gradient
class TwoLayerNet:
def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):
# 输入层神经元数,隐藏层神经元数,输出层神经元数
self.params = dict() # 用于保存神经网络的参数,使用self.params = {}不符合代码规范
self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size) # 第一层权重
# 返回一个input_size行hidden_size列的矩阵,在标准正态分布(高斯分布)中返回;
self.params['b1'] = np.zeros(hidden_size) # 第一层偏置,设置为0
self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size) # 第二层权重
# 返回一个hidden_size行output_size列的矩阵,在标准正态分布(高斯分布)中返回;
self.params['b2'] = np.zeros(output_size) # 第二层偏置,设置为0
def predict(self, x): # 预测函数
w1, w2 = self.params['W1'], self.params['W2'] # 变量在内置函数中用小写
b1, b2 = self.params['b1'], self.params['b2']
a1 = np.dot(x, w1) + b1 # x和w1矩阵点乘+第一层偏置
z1 = sigmoid(a1)
a2 = np.dot(z1, w2) + b2 # z1和w2矩阵点乘+第二层偏置
y = softmax(a2)
return y
def loss(self, x, t): # 损失函数,x为输入数据,t为监督数据
y = self.predict(x)
return cross_entropy_error(y, t) # 交叉熵误差,y为预测结果,t为监督数据(正确解标签)
def accuracy(self, x, t): # 精度
y = self.predict(x)
y = np.argmax(y, axis=1) # 返回矩阵y在行方向的最大值下标
t = np.argmax(t, axis=1) # 返回矩阵t在行方向的最大值下标
accuracy = np.sum(y == t) / float(x.shape[0])
# 计算识别率;np.sum(y == t)结果为y==t的个数;x.shape[0]结果为矩阵x的行数
return accuracy
def numerical_gradient(self, x, t): # 基于数值微分,计算各个参数相对于损失函数的梯度;x为输入数据,t为监督数据
loss_w = lambda w: self.loss(x, t) # lambda表达式是一个匿名函数
grads = dict() # 保存梯度变量
grads['W1'] = numerical_gradient(loss_w, self.params['W1'])
grads['b1'] = numerical_gradient(loss_w, self.params['b1'])
grads['W2'] = numerical_gradient(loss_w, self.params['W2'])
grads['b2'] = numerical_gradient(loss_w, self.params['b2'])
return grads
#####################################################################
#####################################################################
if __name__ == "__main__": # 测试
net = TwoLayerNet(input_size=100, hidden_size=7, output_size=4)
# print(net.params['W1'].shape)
# print(net.params['b1'].shape)
# print(net.params['W2'].shape)
# print(net.params['b2'].shape)
# x = np.random.rand(100, 784)
# y = net.predict(x)
# print(y)
x = np.random.rand(7, 100) # 伪输入数据
t = np.random.rand(7, 4) # 伪正确解标签
grads = net.numerical_gradient(x, t) # 计算梯度
print(grads['W1'].shape)
print(grads['b1'].shape)
print(grads['W2'].shape)
print(grads['b2'].shape)