对mnist数据集使用2层神经网络(1层隐藏层)实现。
1、2层神经网络的类
将2层神经网络实现为一个twolayernet的类:
class twolayernet: def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01): # 初始化权重 self.params = {} self.params['w1'] = weight_init_std * np.random.randn(input_size, hidden_size) self.params['b1'] = np.zeros(hidden_size) self.params['w2'] = weight_init_std * np.random.randn(hidden_size, output_size) self.params['b2'] = np.zeros(output_size) 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 z1 = sigmoid(a1) a2 = np.dot(z1, w2) + b2 y = softmax(a2) return y # x:输入数据, t:监督数据 def loss(self, x, t): y = self.predict(x) return cross_entropy_error(y, t) def accuracy(self, x, t): y = self.predict(x) y = np.argmax(y, axis=1) t = np.argmax(t, axis=1) accuracy = np.sum(y == t) / float(x.shape[0]) return accuracy # x:输入数据, t:监督数据 def numerical_gradient(self, x, t): loss_w = lambda w: self.loss(x, t) grads = {} 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 def gradient(self, x, t): w1, w2 = self.params['w1'], self.params['w2'] b1, b2 = self.params['b1'], self.params['b2'] grads = {} batch_num = x.shape[0] # forward a1 = np.dot(x, w1) + b1 z1 = sigmoid(a1) a2 = np.dot(z1, w2) + b2 y = softmax(a2) # backward dy = (y - t) / batch_num grads['w2'] = np.dot(z1.t, dy) grads['b2'] = np.sum(dy, axis=0) da1 = np.dot(dy, w2.t) dz1 = sigmoid_grad(a1) * da1 grads['w1'] = np.dot(x.t, dz1) grads['b1'] = np.sum(dz1, axis=0 return grads定义了初始化函数__init__,其中params变量w1,2分别是第1,2层的权重,b1,2分别是1,2层的偏置。初始化函数中包含输入层、隐藏层和输出层的神经元数,w1是随机生成的大小为输入层神经元数量(m)*隐藏层神经元数量的矩阵(n),b1是隐藏层神经元数量(n)的全0一维数组,w2是随机生成的大小为隐藏层神经元数量(n)*输出层神经元数量(k)的矩阵,b2是输出层神经元数量(k)的全0一维数组。
定义了predict函数,表明网络结构,输入x权重+偏置进行激活得到隐藏层z1,z1权重+偏置进行激活得到输出y。
定义损失函数loss,使用的是交叉熵误差。
定义精确度函数accuracy,计算输出与标签一致(即正确识别)的概率。
定义了数值微分求权重梯度的函数numerical_gradient,返回梯度值,之前介绍过。
定义了另一种求权重梯度的方法,后面介绍。
上述代码中涉及的两个变量params和grads是字典型实例变量,前者保存了神经网络中全部的参数,后者保存了各个参数的梯度。
2、mini-batch的实现
定义了2层神经网络的类相当于对神经网络进行封装形成一个模块,需要的时候设计参数即可直接调用。现在对mnist数据集进行学习,使用这个封装好的2层神经网络。
# 读入数据(x_train, t_train), (x_test, t_test) = load_mnist(normalize=true, one_hot_label=true)network = twolayernet(input_size=784, hidden_size=50, output_size=10)iters_num = 10000 # 适当设定循环的次数train_size = x_train.shape[0]batch_size = 100learning_rate = 0.1# 获取mini-batchfor i in range(iters_num): batch_mask = np.random.choice(train_size, batch_size) x_batch = x_train[batch_mask] t_batch = t_train[batch_mask]# 计算梯度 #grad = network.numerical_gradient(x_batch, t_batch) grad = network.gradient(x_batch, t_batch)# 更新参数 for key in ('w1', 'b1', 'w2', 'b2'): network.params[key] -= learning_rate * grad[key]# 记录学习过程 loss = network.loss(x_batch, t_batch) train_loss_list.append(loss)读入数据后,调用了2层神经网络的类,设置好函数完成调用,其中输入神经元为784个(图片像素为28*28),隐藏层50个神经元,输出层10个神经元(对应0-9的分类)。
设置超参数,包括学习的次数iters_num,训练数据的数量train_size,一次随机选取的训练数据的个数batch_size,学习率learning_rate。
获取mini-batch,计算mini-batch中的梯度,有两种计算方法数值微分和后面会介绍的高效方法,任意一种都行。通过grad函数更新参数w1,w2,b1,b2,使参数向梯度方向即使损失函数减小的方向移动,保存每一次更新的损失函数的值,后续绘图可以观察损失函数的变化。损失函数在不断减小,说明神经网络确实在学习。
3、基于测试数据的评价
损失函数的值是某一个mini-batch的损失函数的值,不能说明在其他数据集上也能有同等程度的表现,神经网络的学习必须确认是否能识别训练数据之外的其他数据,即确认是否会发生过拟合。
下面的代码会对训练和测试数据的每一个epoch记录识别精度。一个epoch表示学习中所有数据均被使用过一次的更新次数,训练数据有60000个,mini-batch是100个,那么重复随机梯度下降法600次,所有训练数据就都被看过了,因此600次是一个epoch。
train_acc_list = []test_acc_list = []iter_per_epoch = max(train_size / batch_size, 1)if i % iter_per_epoch == 0: train_acc = network.accuracy(x_train, t_train) test_acc = network.accuracy(x_test, t_test) train_acc_list.append(train_acc) test_acc_list.append(test_acc) print(train acc, test acc | + str(train_acc) + , + str(test_acc))# 绘制图形markers = {'train': 'o', 'test': 's'}x = np.arange(len(train_acc_list))plt.plot(x, train_acc_list, label='train acc')plt.plot(x, test_acc_list, label='test acc', linestyle='--')plt.xlabel(epochs)plt.ylabel(accuracy)plt.ylim(0, 1.0)plt.legend(loc='lower right')plt.show()每经历一个epoch就会对所有训练和测试数据计算精度,然后绘制训练和测试精确度的变化,训练和测试的精度在慢慢提高且基本重叠,说明没有过拟合。
四方光电引领行业技术创新,与国际同行实力竞技
基于Yocto Project的定制嵌入式Linux产品设计浅析
激光雕刻技术在陶瓷密封环的工艺优点
Mini LED势头逐渐崛起,未来市场将发生改变
汽车通信芯片汇总梳理
手写数字识别神经网络的实现(1)
美国国土安全部测试面部识别技术,系统的最高准确率达96%
中国工程院院士倪光南表示未来RISC-V可能是中国芯片业的一个机遇
20个半导体项目落户长沙!打造新一代半导体材料技术及产业发展中心
基于有机场效应晶体管(OFET)的生物传感器
国产C919大型客机计划在2017年上半年“首飞”
比特币相关的法币通道有哪些付款方式
边缘云和5G将定义下一个网络时代
一颗iPhone7的FPGA芯片既然暴露苹果对AI的动向
如何对IIoT传感器进行选型
欧菲光研发基于iToF+RGB深度测量技术的3D智能深度相机
IDC:2年内将有两家PC厂商退出市场
华卓精科获8700万的战略投资 推动光刻机国产化
交互的艺术:协作机器人如何定义新一代的人机关系?
学生宿舍用电安全监控系统