# coding: utf-8
import sys, os
sys.path.append(os.pardir) # 为了导入父目录中的文件而进行的设定
import numpy as np
from common.functions import softmax
#输出:神经网络梯度下降dw
def numerical_gradient(f, x):
'''
梯度下降
参数 :函数f 和权重W
返回:梯度 dw
'''
h = 1e-4 # 0.0001
grad = np.zeros_like(x)
it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite']) #http://www.zzvips.com/article/199898.html nditer详解
while not it.finished: #df/dw12 df/dw13
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
def softmax(x):
'''
#分类问题用softmax激活函数
使输出层的个个神经元都受到所有输入信号的影响
参数: x==> z= kx+b
返回: 归一化的概率值
'''
if x.ndim == 2:
x = x.T
x = x - np.max(x, axis=0) #鱼书上67页 减去最大值保证 exp可以被正确计算
y = np.exp(x) / np.sum(np.exp(x), axis=0)
return y.T #当程序运行到第一个return语句的时候,即返回并退出def的函数定义,不会再运行第二个return。
x = x - np.max(x) # 溢出对策
return np.exp(x) / np.sum(np.exp(x))
def cross_entropy_error(y, t):
'''
#损失函数minni-batch交叉熵误差实现 y是神经网络的输出
功能:计算所有训练数据损失函数的总和
参数: 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) #argmax(f(x))就是使f(x)值最大的那个自变量x
batch_size = y.shape[0] #矩阵的行数
return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size #91页内容
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
x = np.array([0.6, 0.9])
t = np.array([0, 0, 1])
net = simpleNet() #108页 详解
f = lambda w: net.loss(x, t) #这里定义的是一个伪参数
dW = numerical_gradient(f, net.W)
print(dW)