文章目录

  • 从数据中学习
    • 数据驱动
      • 一种方案
    • 训练数据和测试数据
  • 损失函数
    • 均方误差
    • 交叉熵误差
    • mini-batch学习
  • 数值微分
    • 导数
    • 数值微分的例子
    • 偏导数
      • 求解两个关于偏导数的例子
        • 题目一
        • 题目二
  • 梯度
    • 梯度法
    • 神经网络的梯度
  • 学习算法的实现
    • 2层神经网络的类
    • mini-batch的实现
    • 基于测试数据的评价

上一章介绍了神经网络的概要,重点关注了神经网络在识别时进行的处理
链接
这一章的“学习”是指从训练数据中自动获取最优权重参数的过程,为了能够学习,导入损失函数这一指标。我们学习的目的就是以该损失函数为基准,找出能使它的值达到最小的权重参数。

从数据中学习

神经网络的特征就是可以从数据中学习,指的是由数据自动决定权重参数的值。
之前感知机对照真值表人工设定了3个参数值,而实际的神经网络参数的数量成千上万甚至过亿,想用人工决定参数的值就不可能了。这一章就是介绍神经网络的学习,即利用数据决定参数值的方法。

数据驱动

数据是机器学习的核心。机器学习的方法是极力避免人为介入,尝试从收集到的数据中发现答案。例如设计一个识别5的程序,人可以很简单的识别出,但却很难明确说出是基于何种规律而识别出5。可以通过数据来解决这个问题:

一种方案

先从图像中提取特征量,再用机器学习技术学习这些特征量的模式。这里的特征量是指可以从输入数据中准确提取本质数据的转换器。使用这些特征量将图像数据转换为向量,然后对转换后的向量使用机器学习中的SVM,KNN等分类器进行学习。

注意点:将图像转换为向量时使用的特征量仍然由人设计。对于不同的问题,必须设计专门的特征量,才能得到好的结果。

如图神经网络直接学习图像本身,第二个路线中特征量仍是由人工设计的。神经网络的优点是对所有的问题都可以用同样的流程来解决,通过不断学习所提供的数据,尝试发现待求解的问题的模式。

训练数据和测试数据

机器学习中,一般将数据分为训练数据测试数据两部分来进行学习和实验等。首先使用训练数据学习,寻找最优的参数,然后使用测试数据评价训练得到的模型的实际能力。之所以这样做就是追求模型的泛化能力,此外训练数据也可以称为监督数据。

获得泛化能力是机器学习的最终目标。仅通过一个数据集去学习和评价参数,会导致对某个数据集过度拟合的过拟合状态。

损失函数

神经网络的学习通过某个指标表示现在的状态,然后以这个指标为基准,寻找最优权重参数。所用的指标称为损失函数(loss function)。这个损失函数可以使用任意函数,一般用均方误差和交叉熵误差

均方误差

可用作损失函数的函数有很多,其中最有名的是均方误差(mean squared error)

y k y_k yk​表示神经网络的输出, t k t_k tk​表示监督数据, k k k表示数据的维数
均方误差会计算神经网络的输出和正确解监督数据的各个元素之差的平方,再求总和。

def mean_squared_error(y,t):return 0.5 * np.sum((y-t)**2)

实际计算

import numpy as npdef mean_squared_error(y,t):return 0.5 * np.sum((y-t)**2)y = [0,0,1,0,0,0,0]
t = [0.1,0.05,0.6,0.0,0.05,0.1,0.0]print(mean_squared_error(np.array(y),np.array(t)))

交叉熵误差

交叉熵误差(cross entropy error)也经常被用作损失函数
log表示以e为底的自然对数, y k y_k yk​是神经网络的输出, t k t_k tk​是正确解标签(我个人觉得 l o g y k logy_k logyk​写成 l n y k lny_k lnyk​更眼熟一点 )

def cross_entropy_error(y,t):delta = 1e-7return -np.sum(t * np.log(y + delta))

计算np.log时,加上了一个微小值delta,防止负无限大的发生
简单计算:

def cross_entropy_error(y,t):delta = 1e-7return -np.sum(t * np.log(y + delta))y = [0,0,1,0,0,0,0]
t = [0.1,0.05,0.6,0.0,0.05,0.1,0.0]print(cross_entropy_error(np.array(y),np.array(t)))

mini-batch学习

机器学习使用训练数据进行学习,就是针对训练数据计算损失函数的值,找出使该值尽可能小的参数。所以计算损失函数时必须将所有的训练数据作为对象。

之前的例子都是针对单个数据的损失函数,若要所有训练数据的损失函数的总和,以交叉熵误差为例,可以写成以下形式

t n k t_nk tn​k表示第n个数据的第k个元素的值,式子看起来有点复杂,其实只是把求单个数据的损失函数的式扩大到了N份数据,不过最后还是要除以N进行正规化。这样就能得到单个数据的“平均损失函数”。通过这样的平均化,可以获得和训练数据的数量无关的统一指标。

另外,MNIST数据集的训练数据有60000个,如果以全部数据为对象求损失函数的和,计算会花费很多时间,遇上几千万以上的数据量更难求。因此需要我们从全部数据中选出一部分,作为全体数据的“近似”。神经网络的学习就是从训练数据中选出一部分数据(称为mini-batch,小批量),然后对每个mini-batch进行学习。例如从60000个训练数据中随机选择100笔,再用这100笔数据进行学习。这种学习方式称为mini-batch学习

读入MNIST数据集的代码:

import sys,os
sys.path.append(os.pardir)
import numpy as np
from dateset.mnist import load_mnist(x_train,t_train),(x_test,t_test) = \load_mnist(normalize = True,one_hot_label = True)print(x_train.shape)  # (60000. 784)
print(t_train.shape)  # (60000, 10)

通过设定参数one_hot_label = True,可以得到one_hot表示(仅正确解标签为1,其余为0的数据结构),代码中的两行注释表示训练数据有60000个,输入数据是784维(28×28)的图像数据,监督数据是10维的数据。

从这个训练数据中随机抽取10笔数据,可以使用numpy的np.random.choice(),写成如下形式:

trian_size = x_train.shape[0]
batch_size = 10
batch_mask = np.random.choice(trian_size,batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]

使用np.random.choice()可以从指定的数字中随机选择想要的数字,可以得到一个包含被选数据的索引的数组,然后只需指定这些随机选出的索引,取出mini-batch,然后使用这个mini-batch计算损失函数即可。

数值微分

梯度法使用梯度的信息决定前进的方向

导数

导数表示的是某个瞬间的变化量,定义成以下的式子:

左边符号表示f(x)关于x的导数,即f(x)相对于x的变化程度

# 不好的示例实现
def numerical_diff(f,x):h = 10e-50return (f(x+h)-f(x))/h

这个函数有两个参数,函数 f 和传给函数 f 的参数 x ,这段代码两处地方需要改进,想把尽可能小的值赋给 h,所以采用了10e-50这个微小值,但会产生舍入误差。(因省略小数的精细部分的数值而造成最终的计算结果上的误差)

如果用32位的浮点数来表示1e-50,就会变成0.0,无法正确表示,使用过小的值会造成计算上的问题,可以将h改成10^-4

第二个要改进的地方与 f 的差分有关,真的导数对应函数在x处的斜率(切线),但在代码实现上是(x+h)和 x 之间的斜率,两者得到的导数值在严格意义上并不一致,这个差异的出现是因为 h 不可能无限接近0

所以计算 f 在(x+h)和(x-h)之间的差分,也成为中心差分

def numerical_diff(f,x):h = 1e-4 # 0.0001return (f(x+h)-f(x-h)) / (2*h)

数值微分的例子

尝试用上述的数值微分对简单函数进行求导

def func1(x):return 0.01*x**2 + 0.1*x

绘制图像

import numpy as np
import matplotlib.pyplot as pltx= np.arange(0.0,20.0,0.1)  # 0到20,0.1为单位
y= func1(x)
plt.xlabel("x")
plt.ylabel("f(x)")
plt.plot(x,y)
plt.show()


来计算一下这个函数在x=5和x=10的导数

print(numerical_diff(func1,5))
print(numerical_diff(func1,10))


得出的结果与真的导数误差极为小,基本上可以看作相等

画出x=5的切线,完整代码如下:

def numerical_diff(f,x):h = 1e-4 # 0.0001return (f(x+h)-f(x-h)) / (2*h)def func1(x):return 0.01*x**2 + 0.1*ximport numpy as np
import matplotlib.pyplot as pltx= np.arange(0.0,20.0,0.1)  # 0到20,0.1为单位
y= func1(x)
plt.xlabel("x")
plt.ylabel("f(x)")def tangent_line(f, x):d = numerical_diff(f, x)print(d)y = f(x) - d*xreturn lambda t: d*t + ytf = tangent_line(func1, 5)
y2 = tf(x)plt.plot(x,y)
plt.plot(x,y2)
plt.show()

偏导数


具有两个变量的函数

def func2(x):return x[0]**2 + x[1]**2

画一下这个函数的图像

来求该函数的导数,但是式中有两个变量,所以要区分对 x 0 x_0 x0​还是 x 1 x_1 x1​进行求导数,此外将有多个变量的函数的导数称为偏导数,用数学式可以写成

求解两个关于偏导数的例子

题目一

def numerical_diff(f,x):h = 1e-4 # 0.0001return (f(x+h)-f(x-h)) / (2*h)def func_t1(x0):return x0*x0 + 4.0**2.0print(numerical_diff(func_t1,3.0))

题目二

def func_t2(x1):return 3.0**2.0 + x1*x1  print(numerical_diff(func_t2,4.0))


与解析解的导数基本一致,偏导数与单变量的导数一样,都是求某个某个地方的斜率。不过偏导数需要将多个变量中的某一变量定为目标变量,并将其他变量固定为某个值。

梯度

上面的例子中计算了 x 0 x_0 x0​和 x 1 x_1 x1​的偏导数,而一起计算两个的偏导数

此外,像这样由全部变量的偏导数汇总而成的向量称为梯度(gradient)

import numpy as npdef numerical_gradient(f,x):h = 1e-4 # 0.0001grad = np.zeros_like(x)  # 生成和x形状相同的数组for idx in range(x.size):tmp_val = x[idx]# f(x+h)的计算x[idx] = tmp_val + hfxh1 = f(x)# f(x-h)的计算x[idx] = tmp_val - hfxh2 = f(x)grad[idx] = (fxh1 - fxh2) / (2*h)x[idx] = tmp_val # 还原值return grad

函数numerical_gradient(f,x)执行的处理和求单变量的数值微分基本没有区别,参数 f 为函数,x为numpy数组,该函数对数组 x 的各个元素求数值微分。现在用它来求点(3,4),(0,2),(3,0)处的梯度

print(numerical_gradient(func2,np.array([3.0,4.0])))
print(numerical_gradient(func2,np.array([0.0,2.0])))
print(numerical_gradient(func2,np.array([3.0,0.0])))



将该函数的梯度画在图上

# coding: utf-8
# cf.http://d.hatena.ne.jp/white_wheels/20100327/p3
import numpy as np
import matplotlib.pylab as plt
from mpl_toolkits.mplot3d import Axes3Ddef _numerical_gradient_no_batch(f, x):h = 1e-4 # 0.0001grad = np.zeros_like(x)for idx in range(x.size):tmp_val = x[idx]x[idx] = float(tmp_val) + hfxh1 = f(x) # f(x+h)x[idx] = tmp_val - h fxh2 = f(x) # f(x-h)grad[idx] = (fxh1 - fxh2) / (2*h)x[idx] = tmp_val # 还原值return graddef numerical_gradient(f, X):if X.ndim == 1:return _numerical_gradient_no_batch(f, X)else:grad = np.zeros_like(X)for idx, x in enumerate(X):grad[idx] = _numerical_gradient_no_batch(f, x)return graddef function_2(x):if x.ndim == 1:return np.sum(x**2)else:return np.sum(x**2, axis=1)def tangent_line(f, x):d = numerical_gradient(f, x)print(d)y = f(x) - d*xreturn lambda t: d*t + yif __name__ == '__main__':x0 = np.arange(-2, 2.5, 0.25)x1 = np.arange(-2, 2.5, 0.25)X, Y = np.meshgrid(x0, x1)X = X.flatten()Y = Y.flatten()grad = numerical_gradient(function_2, np.array([X, Y]) )plt.figure()plt.quiver(X, Y, -grad[0], -grad[1],  angles="xy",color="#666666")#,headwidth=10,scale=40,color="#444444")plt.xlim([-2, 2])plt.ylim([-2, 2])plt.xlabel('x0')plt.ylabel('x1')plt.grid()plt.legend()plt.draw()plt.show()


如图该函数的梯度呈现为有向向量(箭头),指向了最低处。实际上梯度会指向各点处的函数值降低的方向。更严格的讲,梯度指示的方向是各点处的函数值减小最多的方向。(重要性质)

梯度法

机器学习的主要任务就是在学习中寻找最优参数(权重和偏置),这里的最优参数就是损失函数取最小值时的参数。但通常情况下损失函数很复杂,参数空间庞大,不知道在何处取最小值,只能通过巧妙使用梯度来寻找函数最小值(或者尽可能小的值)的方法就是梯度法。

就如上面的重要性质讲的一样,梯度指示的方向是各点处的函数值减小最多的方向。所以无法保证梯度所指的方向就是函数的最小值或者真正应该前进的方向。实际上在复杂的函数中,梯度指示的方向基本上都不是函数值最小处。虽然梯度的方向并不一定指向最小值,但沿着它的方向能最大限度地减小函数的值。

在梯度法中,函数的取值从当前位置沿着梯度方向前进一段距离,然后在新的地方重新求梯度,再沿着新梯度方向前进,如此反复,不断沿梯度方向前进,逐渐减少函数值的过程就是梯度法

尝试用数学式来表示梯度法“

η \eta η表示更新量,也称为学习率(learning rate)。学习率决定在一次学习中,应该学习多少,以及在多大程度上更新参数。

上面的数学式表示更新一次的式子,这个步骤会反复执行,逐渐减少函数值。学习率需要事先确定为某个值,比如0.01或者0.001。为了达到合适的值,一般都会边改变值边确认学习是否正确进行。

def gradient_descent(f,init_x,lr=0.01,step_num=100):x = init_xfor i in range(step_num):grad = numerical_gradient(f,x)x -= lr * gradreturn x

参数 f 是要进行最优化的函数,init_x是初始值,lr 是学习率,step_num是梯度法的重复次数。
numerical_gradient(f,x)是之前的求函数梯度,用该梯度乘以学习率得到的值进行更新操作。

使用这个函数可以求极小值

def func2(x):return x[0]**2 + x[1]**2init_x = np.array([-3.0,4.0])
print(gradient_descent(func2,init_x=init_x,lr=0.1,step_num=100))


设置初始值为(-3.0,4.0),最终结果为(-6.1e-10,8.1e-10),非常接近(0,0),接近真的最小值。用图来表示梯度法的更新过程,原点处是最低的地方,函数的取值一点点在向其靠近。

# coding: utf-8
import numpy as np
import matplotlib.pylab as plt
from gradient_2d import numerical_gradientdef gradient_descent(f, init_x, lr=0.01, step_num=100):x = init_xx_history = []for i in range(step_num):x_history.append( x.copy() )grad = numerical_gradient(f, x)x -= lr * gradreturn x, np.array(x_history)def function_2(x):return x[0]**2 + x[1]**2init_x = np.array([-3.0, 4.0])    lr = 0.1
step_num = 20
x, x_history = gradient_descent(function_2, init_x, lr=lr, step_num=step_num)plt.plot( [-5, 5], [0,0], '--b')
plt.plot( [0,0], [-5, 5], '--b')
plt.plot(x_history[:,0], x_history[:,1], 'o')plt.xlim(-3.5, 3.5)
plt.ylim(-4.5, 4.5)
plt.xlabel("X0")
plt.ylabel("X1")
plt.show()


学习率过大过小都会影响最后的结果

init_x = np.array([-3.0,4.0])
print(gradient_descent(func2,init_x=init_x,lr=10.0,step_num=100))   # 学习率为10
print(gradient_descent(func2,init_x=init_x,lr=1e-10,step_num=100))  # 学习率为1e-10



过大会发散为一个很大的值,学习率过小的话,基本上没更新就结束了。学习率这种超参数
需要人工设定尝试多个值。

神经网络的梯度

神经网络的学习也要求梯度。这里的梯度是指损失函数关于权重参数的梯度。有一个形状为2*3的权重 W 的神经网络,损失函数用 L L L 表示


的元素由各个元素关于 W 的偏导数构成。 例如第一行第一列元素表示当 w w w 11稍微变化时,损失函数 L L L 会发生多大变化。

下面以一个简单的神经网络为例,来实现求梯度的代码,为此实现一个名为 simpleNet 的类

import sys, os
sys.path.append(os.pardir)  # 为了导入父目录中的文件而进行的设定
import numpy as np
from common.functions import softmax, cross_entropy_error
from common.gradient import numerical_gradientclass simpleNet:def __init__(self):self.W = np.random.randn(2,3)def predict(self, x):return np.dot(x, self.W)def loss(self, x, t):z = self.predict(x)y = softmax(z)loss = cross_entropy_error(y, t)return loss

这里使用了softmax和cross_entropy_error方法以及numerical_gradient方法。simpleNet类只有一个实例变量,即形状为2×3的权重参数。他有两个方法,一个是用于预测的predict(x),另一个是用于求损失函数值的loss(x,t)。这里的参数x接收输入数据,t接收正确解标签

def softmax(x):if x.ndim == 2:x = x.Tx = x - np.max(x, axis=0)y = np.exp(x) / np.sum(np.exp(x), axis=0)return y.T x = x - np.max(x) # 溢出对策return np.exp(x) / np.sum(np.exp(x))def cross_entropy_error(y, t):if y.ndim == 1:t = t.reshape(1, t.size)y = y.reshape(1, y.size)# 监督数据是one-hot-vector的情况下,转换为正确解标签的索引if t.size == y.size:t = t.argmax(axis=1)batch_size = y.shape[0]return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_sizedef numerical_gradient(f, x):h = 1e-4 # 0.0001grad = np.zeros_like(x)it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])while not it.finished:idx = it.multi_indextmp_val = x[idx]x[idx] = float(tmp_val) + hfxh1 = f(x) # f(x+h)x[idx] = tmp_val - h fxh2 = f(x) # f(x-h)grad[idx] = (fxh1 - fxh2) / (2*h)x[idx] = tmp_val # 还原值it.iternext()   return grad

学习算法的实现

复习一下神经网络的学习步骤:
前提
神经网络存在合适的权重和偏置,调整权重和偏置以便拟合训练数据的过程称为“学习”,神经网络的学习分为下面四个步骤:

步骤1(mini-batch)
从训练数据中随机选出一部分数据,这部分数据称为mini-batch。我们目标是减小mini-batch的损失函数的值

步骤2(计算梯度)
为了减少mini-batch的损失函数的值,需要求出各个权重参数的梯度。梯度表示损失函数的值减少最多的方向

步骤3(更新参数)
将权重参数沿梯度方向进行微小更新

步骤4(重复)
重复步骤1,步骤2,步骤3

这个学习方法通过梯度下降法更新参数,使用的数据是随机选择的mini batch数据,所以又称为随机梯度下降法(stochastic gradient descent)。一般由一个名为SGD的函数来实现。下面来实现手写数字识别的神经网络,这里以2层神经网络(隐藏层为1层的网络)为对象,使用MNIST数据集进行学习。

2层神经网络的类

首先将这个2层神经网络实现为一个名为TwoLayerNet的类,实现过程如下

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
from common.functions import *
from common.gradient import numerical_gradientclass 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) + b1z1 = sigmoid(a1)a2 = np.dot(z1, W2) + b2y = 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 gradsdef 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]# forwarda1 = np.dot(x, W1) + b1z1 = sigmoid(a1)a2 = np.dot(z1, W2) + b2y = softmax(a2)# backwarddy = (y - t) / batch_numgrads['W2'] = np.dot(z1.T, dy)grads['b2'] = np.sum(dy, axis=0)da1 = np.dot(dy, W2.T)dz1 = sigmoid_grad(a1) * da1grads['W1'] = np.dot(x.T, dz1)grads['b1'] = np.sum(dz1, axis=0)return grads

TwoLayerNet类有params和grads两个字典型实例变量,前者保存神经网络的参数,后者保存梯度的参数。TwoLayerNet的方法实现,首先是__init__(self,input_size,hidden_size,output_size)方法,是类的初始化方法(初始化就是生成TwoLayerNet实例时被调用的方法)。从第一个参数开始,依次表示输入层的神经元数、隐藏层的神经元数、输出层的神经元数。

进行手写数字识别时,输入图像大小为784(28×28),输出为10个类别,所以指定参数input_size=784、output_size=10,将隐藏层的个数hidden_size设置为一个合适的值即可。

predict(self,x)和accuracy(self,x,t)的实现和上一章的神经网络的推理过程基本一样。loss(self,x,t)是计算损失函数值的方法。这个方法会基于predict()的结果和正确解标签,计算交叉熵误差。剩下的numerical_gradient(self,x,t)方法会计算各个参数的梯度。根据数值微分,计算各个参数相对于损失函数的梯度。另外,gradient(self,x,t)是下一章要实现的地方,该方法使用误差反向传播法高效的计算梯度。

mini-batch的实现

神经网络的学习就是mini-batch学习,就是从训练数据中随机选择一部分数据,在意这些mini-batch为对象,使用梯度法更新参数的过程。

import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from two_layer_net import TwoLayerNet(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)train_loss_list = []# 超参数
iters_num = 10000
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.1network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)for i in range(iters_num):# 获取mini-batchbatch_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)

这里mini-batch大小为100,需要每次从60000个训练数据中随机取出100个数据(图像数据和正确解标签数据)。然后对这个包含100笔数据的mini-batch求梯度,使用随机梯度下降法(SGD)更新参数。

基于测试数据的评价

通过反复学习可以使损失函数的值逐渐减小,不过这个损失函数的值,严格讲是“对训练数据的某个mini-batch的损失函数”的值。训练数据的损失函数值减小,光有这个结果还不能说明该神经网络在其他数据集上也一定能有同等程度的表现。

神经网络需要防止过拟合,要掌握泛化能力。对代码进行修改,下面的代码在进行学习的过程中会定期地对训练数据和测试数据记录识别精度。每经过一个 epoch ,都会记录训练数据和测试数据的识别精度。

修改的代码:

import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from two_layer_net import TwoLayerNet# 读入数据
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)train_loss_list = []
train_acc_list = []
test_acc_list = []
# 平均每个epoch的重复次数
iter_per_epoch = max(train_size / batch_size, 1)# 超参数
iters_num = 10000  # 适当设定循环的次数
batch_size = 100
learning_rate = 0.1network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)for 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)# 计算每个epoch的识别精度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))

之所以要计算每一个epoch的识别精度,是因为如果for语句的循环中一只计算识别精度,会花费太多时间。并且也没有必要频繁记录识别精度,所以才会经过一次epoch就记录一次训练数据的识别精度。

深度学习入门之神经网络的学习相关推荐

  1. 深度学习入门之神经网络的学习思维导图

    第4章 神经网络的学习思维导图

  2. 深度学习入门-ANN神经网络参数最优化问题(SGD,Momentum,AdaGrad,RMSprop,Adam)

    这里写目录标题 1. 参数优化 1.1 随机梯度下降法(SGD) 1.2 Momentum 动量法 1.3 AdaGrad 1.4 RMSprop 1.5 Adam 1. 参数优化 本文总结一下ANN ...

  3. 深度学习入门之神经网络

    神经网络 从感知机到神经网路 神经网络的例子 激活函数出场 激活函数 sigmoid函数 阶跃函数的实现 阶跃函数的图形 sigmoid函数的实现 sigmoid函数和阶跃函数的比较 非线性函数 Re ...

  4. 【吐血推荐】机器学习/深度学习入门资料汇总及学习建议【入门必看】

    机器学习入门,初学者遇到的问题非常多,但最大的问题就是: 资料太多!!!看不完!!!不知道如何取舍!!! 一.机器学习的数学基础 正规的机器学习数学基础主要有: 数学分析(微积分),线性代数,概率论, ...

  5. 强化学习入门教程(附学习大纲)

    零基础,想要入门或从事强化学习研究的同学有福了! CSDN学院特邀资深讲师为大家分享<强化学习深入浅出完全教程>从零基础开始入门强化学习,在教学的过程中,配合   具体案例.代码演示 , ...

  6. 单片机学习入门 我们应该这样学习单片机

    单片机在学习入门的时候需要了解哪些内容呢?我们应该这样学习单片机: 首先:数字I/O的使用 使用按钮输入信号,发光二极管显示输出电平,就可以学习引脚的数字I/O功能,在按下某个按钮后,某发光二极管发亮 ...

  7. 深度学习入门——前馈神经网络

    前馈神经网络作为深度学习基础中的基础,是很多同学入门深度学习的必经之路.由于马上要迎来考试复习周,在这里简单记录一下学习心得. 感知机模型 感知机(perceptron)是深度学习中最基本的元素,很多 ...

  8. 深度学习——02、深度学习入门——卷积神经网络

    神经网络框架 卷积层详解 卷积神经网络组成 1.输入层(INPUT) 2.卷积层(CONV) 3.激活函数(RELU) 4.池化层(POOL) 5.全连接层(FC) 卷积计算流程 将image划分为一 ...

  9. 深度学习入门之神经网络思维导图

    第3章 神经网络思维导图

最新文章

  1. Mybatis解决实体类属性和表字段对应不上
  2. 【微信小程序】 自定义导航栏(navigationStyle=custom)
  3. nginx的常规配置
  4. how to setup a Kubernetes cluster on GCP
  5. [蓝桥杯2019初赛]旋转-找规律
  6. jQuery模拟原生态App上拉刷新下拉加载
  7. 使用 Skeleton Screen 提升用户感知体验
  8. 一篇好文之Android文本软键盘全解
  9. 数据结构1800题-错题集-第七章
  10. vt功能对计算机有影响吗,win7怎么开启vt模拟器?电脑开vt有什么坏处?
  11. 酸了,深圳一普通中学老师工资单曝光,秒杀程序员!
  12. Python的eval函数详解
  13. 5.node.js中的事件循环
  14. RobotFrameWork(二)Ride简单使用及快捷键
  15. 探索“发电巨兽”在新基建下,如何拯救限电问题?
  16. 《终结拖延症》读书笔记,作者威廉·克瑙斯
  17. Recsys 2018长篇论文总结
  18. 西门子PLC之间如何建立无线通讯?
  19. android pdf编辑,Foxit PDF SDK
  20. 不要和负能量的人交朋友

热门文章

  1. 2015年9月11日
  2. 深度学习-BP神经网络
  3. 什么是泛型中的限定通配符和非限定通配符 ?
  4. KVM虚拟化技术的-NUMA技术和应用
  5. 东南西北十字图_word画东南西北方向图标 怎么在Word里绘制方向十字图标
  6. iOS 支付 [支付宝 银联 微信]
  7. 互联网中B端客户和C端客户的区别?
  8. Python实现去除图片中的数字水印
  9. 数据库指南-SQL与NoSQL
  10. 【skLearn 回归模型】岭回归 <linear_model.Ridge>