y = h(b+w1x2+w2x2)
b偏置:用于控制神经元被激活的容易程度。
w1、w2:表示各个信号权重的参数,用于控制各个信号的重要性。
激活函数:h()就是激活函数。
x:是输入数据。
y:是输出数据。
常用的激活函数:
sigmoid函数:
def sigmoid(x):
return 1/(1+np.exp(x))
ReLu函数
分类输出函数softmax函数:
def softmax(x):
m = np.max(x)
exp_a = np.exp(x-m)
sum_exp_a = np.sum(exp_a)
return exp_a/sum_exp_a
损失函数:表示神经网络性能的“恶劣程度”的指标,一般用均方误差和交叉熵误差等函数。
梯度法:是为了寻找损失函数的最小值。由全部变量的偏导数汇总而成的向量称为梯度。梯度指示的方向是各点处的函数值减小最多的方向。
小例子
识别手写数字
import sys,os
import numpy as np
sys.path.append(os.pardir)
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)
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)
# print(loss_W)
grads = {}
grads['W1'] = numerical_gradient(loss_W,self.params['W1'])
print(loss_W)
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
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from 手写字network import TwoLayerNet
(x_train,t_train),(x_test,t_test) = load_mnist(normalize=True,one_hot_label=True)
#超参数
iters_num = 10000
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.1
train_loss_list = []
train_acc_list = []
test_acc_list = []
#平均每个epoch的重复次数
iter_per_epoch = max(train_size / batch_size,1)
network = TwoLayerNet(input_size=784,hidden_size=50,output_size=10)
for i in range(iters_num):
#获取mini_batch
batch_mask = np.random.choice(train_size,batch_size)
x_batch = x_train[batch_mask]
t_bacth = t_train[batch_mask]
#计算梯度
#grad = network.numerical_gradient(x_batch,t_bacth)
grad = network.gradient(x_batch,t_bacth)
#更新参数
for key in ('W1','b1','W2','b2'):
network.params[key] -= learning_rate * grad[key]
#记录学习过程
loss = network.loss(x_batch,t_bacth)
train_loss_list.append(loss)
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))
print(x)
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()
反向传播
加法节点的反向传播(+)
将上游的值原封不动的传到下游。
乘法节点的反向传播(*)
会乘以输入信号的翻转值,正向传播是x,反向转播乘y。
除法节点(/)
用y对x求导,上游传过来的值乘这个导数就行。
正向传播
exp()节点
会进行y=exp(x)的计算。
除法节点(/)
会进行y=1/x的计算。
反向传播比争相传播更快。
SGD随机梯度下降法 整体还是比较慢,可以用更牛的算法例如momentum,AdaGrad.
Momentum:增加了阻力,W权重更新变慢。
AdaGrad:改变学习率
第七章卷积神经网络
卷积、填充、步幅。
输出的大小的计算公式
OH = (H + 2P - FH/S) + 1
OW = (W + 2P - FW/S) + 1
池化层
池化是缩小长、高方向上的空间的运算。
特征:没有要学习的参数,通道数不发生变化。
对微小的位置变化具有鲁棒性(健壮性)。(因为是取某块的max值)
Im2col()函数解析