forked from codefan/python-study
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMultiLayerNet.py
More file actions
95 lines (82 loc) · 2.97 KB
/
Copy pathMultiLayerNet.py
File metadata and controls
95 lines (82 loc) · 2.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
from common.functions import sigmoid, softmax, sigmoid_grad, cross_entropy_error
from common.gradient import numerical_gradient
import numpy as np
class MultiLayerNet:
def __init__(self, layerSize, weight_init_std=0.01):
self.l = len(layerSize) - 1
# sigmoid sigmoid_grad
# 随意这个值不能 改变,如果需要改 就需要配对的修改 sigmoid_grad
self.h = sigmoid
self.sigma = softmax
self.W = []
self.B = []
# 初始化权重
for i in range(self.l):
# np.random.randn 为符合高斯分布(正态分布)的随机数据
self.W.append(weight_init_std * np.random.randn(layerSize[i], layerSize[i+1]))
self.B.append(np.zeros(layerSize[i+1]))
def calcLayer(self, A, w, b, h):
return self.h(np.dot(A,w) + b)
def predict(self, x):
A = x
# 隐藏层
for i in range(self.l - 1):
A = self.calcLayer(A, self.W[i], self.B[i], self.h)
# 输出层
return self.calcLayer(A, self.W[self.l-1], self.B[self.l-1], self.sigma)
# 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)
gW = []
gB = []
for i in range(self.l):
gW.append(numerical_gradient(loss_W, self.W[i]))
gB.append(numerical_gradient(loss_W, self.B[i]))
return gW, gB
def gradient(self, x, t):
batch_num = x.shape[0]
# forward
# 输入层
A = []
Z = []
z = x
A.append(x)
Z.append(x)
# 隐藏层
for i in range(self.l - 1):
a = np.dot(z, self.W[i]) + self.B[i]
z = self.h(a)
A.append(a)
Z.append(z)
# 输出层
a = np.dot(z, self.W[self.l-1]) + self.B[self.l-1]
y = self.sigma(a)
A.append(a)
Z.append(y)
# backward
dy = (y - t) / batch_num
gW = []
gB = []
gW.append(np.dot(Z[self.l-1].T, dy))
gB.append(np.sum(dy, axis=0))
for i in range(self.l-2,-1,-1):
# 反向传播 的偏导 就是 W系数,
da = np.dot(dy, self.W[i+1].T)
# 激活函数的偏导
dy = sigmoid_grad(A[i+1]) * da
gW.append(np.dot(A[i].T, dy))
gB.append(np.sum(dy, axis=0))
# numerical_gradient 和这个返回的顺序一致
# gW.reverse() ; gB.reverse()
return gW[::-1], gB[::-1]