【鱼书入门】第2~4章

第2章 感知机

2.3 感知机的实现

2.3.1 简单的实现

def AND(x1,x2):
    w1,w2,theta = 0.5,0.5,0.7
    tmp = x1*w1+x2*w2
    if tmp <= theta:
        return 0
    elif tmp>theta:
        return 1

2.3.2 导入权重和偏置

import numpy as np
x=np.array([0,1])   # 创建数组对象
print(x)
w=np.array((0.5,0.5))
print(w)
b=-0.7    # b = -theta
print(w*x)   # [0.  0.5]
y=np.sum(w*x)+b
print(y)   # -0.19999999999999996,大约为0.2

2.3.3 使用权重和偏置实现

权重,即参数
偏置,调整神经元激活程度的容易程度。
(因为,如果b=-0.1,则说明加权和只要大于0.1,神经元就会被激活;
而如果b=-20,则加权和需得大于20,神经元才会被激活)

# 与门
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(y<=0):
        return 0
    else:
        return 1
# 或门
import numpy as np
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 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

2.5 多层感知机

2.5.1 二层感知机构建 异或门

理论上两层感知机就能构建计算机了,因为研究证明2层计算机可以表示任意函数(严格说是激活函数使用了非线性的sigmoid函数的感知机)。

# 异或门的实现(由与、或、非门综合构成)
def XOR(x1,x2):
    s1=NAND(x1,x2)
    s2=OR(x1,x2)
    y=AND(s1,s2)
    return y

第三章 神经网络

  1. 好消息:即使是复杂的函数,也可以通过多层感知机表示
    坏消息:设置权重的工作,还是由人工进行。
  2. 神经网络的出现,就是为了解决这里的坏消息。
    ------>神经网络可以自动地从数据中学习到 合适的权重参数
  3. 激活函数的作用就是:决定如何来激活输入信号的总和。比如,求和的形式。
    (激活函数也是 连接 感知机 和 神经网络的 桥梁

3.2 激活函数

神经网络的激活函数必须是非线性函数
如果使用线性函数,那么加深神经网络的层数就没有意义了。

3.2.2 阶跃函数的实现

# x只能接受实数(浮点数),但x不能取Numpy数组!如step_function([1.0,2.0])
def step_function(x):   
    if x>0:
        return 1
    else:
        return 0

将上面的函数修改为 支持Numpy数组的形式:

# 前提:对Numpy数组进行不等号运算后,数组的每个元素都会进行 不等号运算
import numpy as np
x=np.array([-1.0,1.0,2.0])
print(x)    # [-1.  1.  2.]
y=x>0
print(y)    # [False  True  True],即y是一个布尔数组
y=y.astype(np.int64)        # .astype()用于将数组的元素类型转换为指定的类型
print(y)    # [0 1 1]

# Numpy技巧实现阶跃函数
def step_function(x):
    y=x>0
    return y.astype(np.int64)

3.2.3 阶跃函数的图像

import matplotlib.pyplot as plt
import numpy as np

def step_function(x):
    return np.array(x>0,dtype=np.int64)

x=np.arange(-5.0,5.0,0.1)   # 生成数组
y=step_function(x)
plt.plot(x,y)
plt.ylim(-0.1,1.1)    # 指定y轴范围
plt.show()

在这里插入图片描述

3.2.4 sigmoid函数的实现

import matplotlib.pyplot as plt
import numpy as np

def sigmoid(x):     # 由于Numpy数组的广播功能,该函数可以接受Numpy数组
    return 1/(1+np.exp(-x))

x=np.arange(-5.0,5.0,1.0)   # 生成数组
y=sigmoid(x)
plt.plot(x,y)
plt.ylim(-0.1,1.1)    # 指定y轴范围
plt.show()

在这里插入图片描述

3.2.7 ReLU函数

import matplotlib.pyplot as plt
import numpy as np

def relu(x): 
    return np.maximum(0,x)

x=np.arange(-5.0,5.0,1.0)   # 生成数组
y=relu(x)
plt.plot(x,y)
plt.ylim(-0.1,1.1)    # 指定y轴范围
plt.show()

在这里插入图片描述

3.3 多维数组的运算

3.3.1当A是二维矩阵,B是一维数组时

总结:np.dot() 运算会根据矩阵的维度和广播机制处理形状不完全匹配的情况,只要满足矩阵乘法的条件(即左侧矩阵的列数 等于 右侧矩阵的行数)。
在这里插入图片描述

3.3.2 神经网络的内积

import numpy as np
x=np.array([1,2])
print(x.shape)
w=np.array([[1,3,5],[2,4,6]])  # 向量的维度大小与矩阵行数一直,则左乘;
print(w.shape)
Y=np.dot(x,w)
print(Y)    # [ 5 11 17]

3.4 3层神经网络的实现

  • 普通表示
import numpy as np

# 隐藏层激活函数
def sigmoid(x):    # h(x)
    return 1/(1+np.exp(-x))

x=np.array([1.0,0.5])
w1=np.array([[0.1,0.3,0.5],[0.2,0.4,0.6]])   # 一行表示左侧一个神经元发射的参数
b1=np.array([0.1,0.2,0.3])
# 输入层-->第1层之间的信号传递
a1=np.dot(x,w1)+b1
print(a1)     # [0.3 0.7 1.1]
z1=sigmoid(a1)
print(z1)     # [0.57444252 0.66818777 0.75026011]

# 第1层-->第2层之间的信号传递
w2=np.array([[0.1,0.4],[0.2,0.5],[0.3,0.6]])
b2=np.array([0.1,0.2])
a2=np.dot(z1,w2)+b2
print(a2)     # [0.51615984 1.21402696]
z2=sigmoid(a2)
print(z2)     # [0.62624937 0.7710107 ]

# 第2层-->输出层之间的信号传递
# 输出层的激活函数也隐藏层不同
def identity_function(x):      # 恒等函数sigma(x)
    return x
w3=np.array([[0.1,0.3],[0.2,0.4]])
b3=np.array([0.1,0.2])
a3=np.dot(z2,w3)+b3
print(a3)
y=identity_function(a3)
print(y)
  • 神经网络表示
# 隐藏层激活函数
def sigmoid(x):    # h(x)
    return 1/(1+np.exp(-x))

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 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)

3.5 输出层的设计(激活函数的选择)

神经网络可以用在分类问题和回归问题上,不过需要根据情况改变输出层的激活函数。

回归问题—>恒等函数
分类问题—>softmaxh函数

import numpy as np

# 计算有溢出风险
def softmax(a):
    exp_a = np.exp(a)
    sum_exp_a = np.sum(exp_a)
    y = exp_a/sum_exp_a
    return a

softmax的指数函数运算时,加上/减去 某个常数不会改变运算结果。

import numpy as np

# softmax的指数函数运算时,加上/减去 某个常数不会改变运算结果。
# 常数取输入信号的最大值
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

3.6 例子–>手写数字识别

3.6.1 MNIST数据集

file:内置函数,返回这个py文件路径
os.path.abspath(file):返回这个文件的绝对路径
os.path.dirname:返回这个文件的上一层目录的路径名
os.pardir返回父目录的字符串,表示父目录的符号(…)

import sys,os
# os.pardir返回父目录的字符串;导入父目录中的文件而进行的设定
sys.path.append("D:/GitRepository/1.start python")    # os.pardir,使用绝对路径
from dataset.mnist import load_mnist
import numpy as np

(x_train,y_train),(x_test,y_test) = load_mnist(flatten = True,normalize = False)
print(x_train.shape)

面临的问题:运行代码发现MNIST在给定网站数据不存在,以至于下载不下来。
解决:通过Mnist数据集中,百度网盘链接下载下来4个.gz文件。将它们放在load_mnist文件所在位置的父目录中,即dataset目录中。
(因为执行load_mnist函数时,会检查.gz文件是否已经在本地,即可跳过远程下载这个步骤。)

3.6.2 显示图片

import sys,os
# # os.pardir返回父目录的字符串;导入父目录中的文件而进行的设定
sys.path.append("D:/GitRepository/1.start python")    # os.pardir,使用绝对路径
from dataset.mnist import load_mnist
import numpy as np
from PIL import Image

(x_train,y_train),(x_test,y_test) = load_mnist(flatten = True,normalize = False)

def img_show(img):
    pil_img = Image.fromarray(np.uint8(img))    # 将 NumPy 数组转换为 Image 对象.from array
                                                # .uint8():确保图像数据格式正确,通常图像的每个像素值在 0 到 255 之间
    pil_img.show()    # 显示图像

img = x_train[0]
lable = y_train[0]
print(lable)

print(img.shape)
img = img.reshape(28,28)
print(img.shape)

img_show(img)

3.6.3 神经网络的推理处理

  • 单个数据
import sys,os
# # os.pardir返回父目录的字符串;导入父目录中的文件而进行的设定
sys.path.append("D:/GitRepository/1.start python")    # os.pardir,使用绝对路径
from dataset.mnist import load_mnist
import numpy as np
import pickle

def sigmoid(x):    # h(x)
    return 1/(1+np.exp(-x))

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

def get_data():
    (x_train,y_train),(x_test,y_test) = load_mnist(normalize=True,flatten = True,one_hot_label=False)
    return x_test,y_test

def init_network():
    with open(r"D:\GitRepository\1.start python\ch03\sample_weight.pkl",'rb') as f:
        network=pickle.load(f)
    return network

def predict(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=softmax(a3)
    return y

x,y=get_data()
network=init_network()
accuracy_cnt = 0
for i in range(len(x)):
    t=predict(network,x[i])
    p=np.argmax(t)    # 获取概率最高的元素的索引
    if p==y[i]:
        accuracy_cnt +=1
print("Accuracy:"+str(float(accuracy_cnt)/len(x)))    # Accuracy:0.9352
  • 批处理
    在这里插入图片描述
import sys,os
# # os.pardir返回父目录的字符串;导入父目录中的文件而进行的设定
sys.path.append("D:/GitRepository/1.start python")    # os.pardir,使用绝对路径
from dataset.mnist import load_mnist
import numpy as np
from PIL import Image
import pickle

def sigmoid(x):    # h(x)
    return 1/(1+np.exp(-x))

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

def get_data():
    (x_train,y_train),(x_test,y_test) = load_mnist(normalize=True,flatten = True,one_hot_label=False)
    return x_test,y_test

def init_network():
    with open(r"D:\GitRepository\1.start python\ch03\sample_weight.pkl",'rb') as f:
        network=pickle.load(f)
    return network

def predict(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=softmax(a3)
    return y

x,y=get_data()
batch_size=100
network=init_network()
accuracy_cnt = 0
for i in range(0,len(x),batch_size):
    x_batch = x[i:i+batch_size]
    t_batch=predict(network,x_batch)
    p=np.argmax(t_batch,axis=1)    # 获取概率最高的元素的索引
    accuracy_cnt += np.sum(p==y[i:i+batch_size])

print("Accuracy:"+str(float(accuracy_cnt)/len(x)))    # Accuracy:0.9352

第四章 神经网络的 学习

引入损失函数这一指标,找出使得损失函数的值最小的权重参数。

4.2 损失函数

4.2.1 均方误差

import numpy as np
# 均方误差
def mean_squared_error(y,t):
    return 0.5*np.sum((y-t)**2)

4.2.2 交叉熵误差

交叉熵误差:由于正确解对应的输出结果决定
正确解对应的输出越大,误差越接近于0;对应的输出越小,误差越大

def cross_entropy_error(y,t):
    delta = 1e-7
    return -np.sum(t*np.log(y+delta))   # 加上delta是为了避免出现 log(0)

4.2.3 mini-batch学习

所有训练数据的损失函数总和 / n —> 单个数据的平均损失函数
为了避免大规模的计算,可从全部数据中选择一部分,作为全部数据的**“近似”**。

np.random.choice可以 从指定的数字中 随机选择 想要的数字。
如:np.random.choice(60000,10)表示:会从0~59999之间随机选择10个数字

import numpy as np

train_size = x_train.shape[0]   # 784
batch_size = 10
batch_mask = np.random.choice(train_size,batch_size)
x_batch = x_train(batch_mask)
y_batch = y_train(batch_mask)

4.2.4 mini-batch版交叉熵误差的实现

  • t为one-hot形式 【对应相乘】
y = np.array([[0.1, 0.3, 0.6]])  # 模型预测概率
t = np.array([[0, 0, 1]])         # one-hot 真实标签
y*t = [[0,0,0.6]]   # 对应相乘
import numpy as np

# 非one-hot版本
def cross_entropy_error(y,t):
    if y.ndim ==1:    # 求单个数据的交叉熵损失函数时
        y = y.reshape(1,y.size)   # # 将y从一维转换为二维
        t = t.reshape(1,t.size)
    
    batch_size = y.shape[0]   # 样本数。就是因为一步才有了前面的if判断
    return -np.sum(t*np.log(y+1e-7))/batch_size   # 由于 广播功能 可以直接计算
  • t为 非one-hot版本 【二维坐标】

y[np.arange(batch_size),t] :从 二维矩阵 中 根据坐标取出 正确值对应的输出值
具体地,[np.arange(batch_size),t]中,np.arange(batch_size)生成的每个数,都会 依次 与 t 组合成二维坐标。
如:[y[0,3],y[1,7],y[2,0],y[3,9],y[4,4]]

# 适用于 非one-hot 编码的标签
def cross_entropy_error(y,t):
    if y.ndim ==1:    # 求单个数据的交叉熵损失函数时
        y = y.reshape(1,y.size)   # # 将y从一维转换为二维
        t = t.reshape(1,t.size)
    
    batch_size = y.shape[0]   # 样本数。就是因为一步才有了前面的if判断
    return -np.sum(np.log(y[np.arange(batch_size),t]+1e-7))/batch_size

4.2.5 为什么要设定损失函数

如果导数为,通过使该权重参数向正方向改变,可以减小损失函数的值;
如果导数为,通过使该权重参数向负方向改变,可以增大损失函数的值。
当导数为0时,无论权重参数向哪个方向变化,损失函数的值都不会改变。

4.3 数值微分

4.3.1 导数

def numerical_diff(f,x):
    h=1e-4     # 0.0001
    return (f(x+h)-f(x-h))/(2*h)    # 可以确保x在中间,也就是所求趋近于x处的导数

4.3.2 偏导数

def numerical_diff(f,x):
    h=1e-4     # 0.0001
    return (f(x+h)-f(x-h))/(2*h)    # 可以确保x在中间,也就是所求趋近于x出的导数

def function_tmp1(x0):
    return x0*x0+4**2
print(numerical_diff(function_tmp1,3))

4.4 梯度.

有全部变量的偏导数汇总而成的向量称为梯度。
负梯度方向是梯度法中变量的更新方向:随着x的增大,函数会减小的方向。
梯度:各点处函数值减小最多的方向,无法保证所指的方向就是函数的最小值或者真正应该前进的方向。

  • 计算梯度
# 基于一个参数计算梯度
import numpy as np
def numerical_gradient(f,x):
    h=1e-4
    grad = np.zero_like(x)   # 返回一个与输入数组 x 具有 相同形状和数据类型 的全零数组

    # 为每一个x自变量计算偏导
    for idx in range(len(x)):
        tmp = x[idx]
        # f(x+h)
        x[idx] = tmp+h
        fxh1=f(x)

        # f(x-h)
        x[idx] = tmp-h
        fxh2 = f(x)

        grad[idx] = (fxh1-fxh2)/(2*h)
        x[idx] = tmp   # 为下一个位置偏导的计算而还原
    return grad
  • 实现梯度下降法
# 基于一个参数计算梯度
import numpy as np
def numerical_gradient(f,x):
    h=1e-4
    grad = np.zeros_like(x)   # 返回一个与输入数组 x 具有 相同形状和数据类型 的全零数组

    # 为每一个x自变量计算偏导
    for idx in range(len(x)):
        tmp = x[idx]
        # f(x+h)
        x[idx] = tmp+h
        fxh1=f(x)

        # f(x-h)
        x[idx] = tmp-h
        fxh2 = f(x)

        grad[idx] = (fxh1-fxh2)/(2*h)
        x[idx] = tmp   # 为下一个位置偏导的计算而还原
    return grad

# 开始下降
def gradent_descent(f,init_x,lr=0.01,step_num=100):
    x = init_x

    # 迭代次数
    for i in range(step_num):
        grad =  numerical_gradient(f,x)   # 计算梯度
        x -= lr*grad
    return x

4.4.2 神经网络的梯度

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_gradient

# 求梯度
class 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  

net = simpleNet()
x = np.array([0.6,0.9])
t = np.array([0,1])

def f(w):
    return  net.loss(x,t)
dw = numerical_gradient(f,net.w)    # 梯度

4.5 学习算法的实现

步骤1:mini-batch:由于mini batch数据是随机选择的,所以又称 随机梯度下降法,由SGD函数实现。
步骤2:计算梯度
步骤3:更新参数
步骤4:重复以上步骤

4.5.1 2层神经网络的类

如何设置权重参数影响神经网络能否学习成功:
权重 使用 符合高斯分布的随机数进行初始化;
偏置 实验 0 进行初始化。

import sys,os
sys.path.append("D:/GitRepository/1.start python")
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 = {}
        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)    # 不用对y进行np.argmax的操作,因为交叉熵损失函数 可以直接计算概率分布之间的差异
    
    # 计算梯度,调用求导函数。(梯度计算-->基于一个变量求导)
    def gradient_gradients(self,x,t):
        loss_w = lambda w:self.loss(w,t)   # lambda式子,可以定义只有一个参数的函数

        # 将每个参数 的 导数 存入grads中,组成梯度向量
        grads = {}
        grads['W1'] = numerical_gradient(loss_w,self.params['W1'])   # numerical_gradient 基于 数值微分 计算梯度。
        grads['b1'] = numerical_gradient(loss_w,self.params['b1'])
        grads['w2'] = numerical_gradient(loss_w,self.params['w2'])
        grads['b1'] = numerical_gradient(loss_w,self.params['b2'])
        return grads

    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

net = TwoLayerNet(input_size=784,hidden_size=100,output_size=10)
x=np.random.rand(100,784)  # 伪输入数据100笔
t=np.random.rand(100,10)

4.5.3 mini-batch的实现

import sys
import numpy as np
sys.path.append("D:/GitRepository/1.start python")
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    # 梯度更新次数为10000次
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.1
network = TwoLayerNet(input_size=784,hidden_size=100,output_size=10)

for i in range(iters_num):
    # 获取mini-batch
    batch_mask = np.random.choice(train_size,batch_size)    # 随机选择mini-batch序号,所以不会遍历到每一个训练数据
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]

    # 计算梯度(向量)
    grad = network.numerical_gradients(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)

4.5.4 基于测试数据的评价

一个epoch,即遍历一次训练数据。

import sys
import numpy as np
sys.path.append("D:/GitRepository/1.start python")
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    # 梯度更新次数为10000次
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.1
network = TwoLayerNet(input_size=784,hidden_size=100,output_size=10)

for i in range(iters_num):
    # 获取mini-batch
    batch_mask = np.random.choice(train_size,batch_size)    # 随机选择mini-batch序号
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]

    # 计算梯度(向量)
    grad = network.numerical_gradients(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_batch,t_batch)
        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))

总结

  1. loss(x,t):return 损失函数计算函数。
  2. numerical_gradient(x,t):return grad.
    基于一个参数计算导数,由于参数可能是一个矩阵/ 向量,所以将 基于数值微分求导的函数 封装为新的函数。
  3. numerical_gradient(x,t):return grads.
    为 损失函数中 的每一个参数计算导数,存入grads中,组成梯度向量grads。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值