2023.1.11
神经网络的学习也要求梯度,而这个梯度是指损失函数关于权重的梯度。
以交叉熵误差函数举例子:
假设权重变化的函数是w,而w就是t的函数,所以有:
代码实现:
import os, sys
import numpy as np
sys.path.append(os.pardir)
def softmax(x): # 一种神经网络的激活函数
if x.ndim == 2: # 判断数组x的维度是否为2
x = x.T # 数组(矩阵)x的转置
x = 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):
delta = 1e-7
return -1 * np.sum(t * np.log(y + delta))
def numerical_gradient(f, x):
h = 1e-4 # 0.0001
grad = np.zeros_like(x)
it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite']) # np.nditer() 迭代器处理多维数组
while not it.finished:
idx = it.multi_index
tmp_val = x[idx]
x[idx] = float(tmp_val) + h
fxh1 = 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
class simplenet: # 神经网络利用测试集的分类工作
def __init__(self):
self.W = np.random.randn(2, 3) # 随机生成一个(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 # 返回损失函数
# 假设神经网络的学习阶段的损失函数
def f(W):
return net.loss(x, t)
def gradient_descent(f, x, lr, step_num): # 利用梯度法求损失函数最小指
init_x = x
for i in range(step_num):
grad = numerical_gradient(f, init_x)
x -= lr * grad
return x
net = simplenet()
print("参与计算的权重:", "\n", net.W)
print("分别输入测试集x0,x1", "\n")
x0 = float(input()) # 假设输入测试集
x1 = float(input())
x = np.array([x0, x1])
y = net.predict(x) # 神经网络推理处理得到 ”分类结果“
print("假设的分类结果:", "\n", y)
y1 = np.argmax(y) # 输出最大索引
t = np.zeros_like(y)
# 正确解标签
for i in range(y.size):
if i == y1:
t[i] = 1
print("监督数据:", "\n", t) # 得到监督数据t
dw = numerical_gradient(f, net.W) # 求取神经网络的学习阶段的损失函数的梯度
print("神经网络的梯度:", "\n", dw) # 内置了神经网络损失函数和权重计算的梯度
print("求取损失函数的最小值", "\n", gradient_descent(f, x, 0.01, 100)) # 内置损失函数 利用梯度法求取损失函数的最小值
numerical_gradient(f,net.W) 的结果dw是一个形状为2×3的二维数组(如图):
这里结合数学意义,我们可以知道, 的值大约是-1,这表示如果w1增加
,那么损失函数E的值会增加
。因此,我们可以知道正值偏导数应该向负方向更新,而正值偏导数应该向正方向更新。
通过神经网络的梯度,可以更好的知道哪个参数的贡献大,怎样更好的去调整参数。