公式化:
a 1 ( 1 ) = w 11 ( 1 ) x 1 + w 12 ( 1 ) x 2 + b 1 ( 1 ) ( 1 ) a_1^{(1)}=w_{11}^{(1)}x_1+w_{12}^{(1)}x_2+b_{1}^{(1)} (1) a1(1)=w11(1)x1+w12(1)x2+b1(1)(1)
a 2 ( 1 ) = w 21 ( 1 ) x 1 + w 22 ( 1 ) x 2 + b 2 ( 1 ) ( 2 ) a_2^{(1)}=w_{21}^{(1)}x_1+w_{22}^{(1)}x_2+b_{2}^{(1)} (2) a2(1)=w21(1)x1+w22(1)x2+b2(1)(2)
a 3 ( 1 ) = w 31 ( 1 ) x 1 + w 32 ( 1 ) x 2 + b 3 ( 1 ) ( 3 ) a_3^{(1)}=w_{31}^{(1)}x_1+w_{32}^{(1)}x_2+b_{3}^{(1)} (3) a3(1)=w31(1)x1+w32(1)x2+b3(1)(3)
写成矩阵的格式:
( a 1 ( 1 ) a 2 ( 1 ) a 3 ( 1 ) ) = ( x 1 x 2 ) ∗ ( w 11 ( 1 ) w 21 ( 1 ) w 31 ( 1 ) w 12 ( 1 ) w 22 ( 1 ) w 32 ( 1 ) ) + ( b 1 ( 1 ) b 2 ( 1 ) b 3 ( 1 ) ) \begin{pmatrix} a_1^{(1)}\\ a_2^{(1)} \\a_3^{(1)} \end{pmatrix}= \begin{pmatrix} x_1&x_2\\ \end{pmatrix} *\begin{pmatrix} w_{11}^{(1)}&w_{21}^{(1)}&w_{31}^{(1)}\\ w_{12}^{(1)}&w_{22}^{(1)}&w_{32}^{(1)}\\ \end{pmatrix}+\begin{pmatrix} b_1^{(1)}\\ b_2^{(1)} \\b_3^{(1)} \end{pmatrix} ⎝⎜⎛a1(1)a2(1)a3(1)⎠⎟⎞=(x1x2)∗(w11(1)w12(1)w21(1)w22(1)w31(1)w32(1))+⎝⎜⎛b1(1)b2(1)b3(1)⎠⎟⎞
即:
A 1 = X ∗ W 1 + B 1 \boldsymbol{A_1}=\boldsymbol{X}*\boldsymbol{W_1}+\boldsymbol{B_1} A1=X∗W1+B1
import numpy as np
X=np.array([1.0,2.0])
W1=np.array([[2.0,1.0,3.0],[1.0,3.0,2.0]])
B1=np.array([2.0,3.0,1.0])
A1=np.dot(X,W1)+B1
print(A1)
运行结果如下:
[ 6. 10. 8.]
def sigmoid(x):
return 1/(1+np.exp(-x))
...
Z1=sigmoid(A1)
print(Z1)
根据上面的一组数据得到的运行结果如下:
[0.99752738 0.9999546 0.99966465]
...
W2=np.array([[0.05,0.02],[0.03,0.01],[0.02,0.01]])
B2=np.array([0.2,0.5])
print(Z1.shape)
print(W2.shape)
print(B2.shape)
A2=np.dot(Z1,W2)+B2
Z2=sigmoid(A2)
print(Z2)
运行结果如下:
[0.57441032 0.63180003]
4. 第 2 层到输出层的信号传递
实现代码如下:
def identity_function(x):
return x
...
W3=np.array([[0.6,0.7],[0.5,0.8]])
B3=np.array([0.5,0.5])
A3=np.dot(Z1,W2)+B3
Z3=identity_function(A3)
print(Z3)
运行结果如下:
[1.16054621 1.40752725]
import numpy as np
def sigmoid(x):
return 1/(1+np.exp(-x))
def identity_function(x):
return x
def init_network(): #权重和偏置的初始化
network={} #定义了一个空列表
network['W1']=np.array([[2.0,1.0,3.0],[1.0,3.0,2.0]]) #只用大写字母表示权重
network['b1']=np.array([2.0,3.0,1.0])
network['W2']=np.array([[0.05,0.02],[0.03,0.01],[0.02,0.01]])
network['b2']=np.array([0.2,0.5])
network['W3']=np.array([[0.6,0.7],[0.5,0.8]])
network['b3']=np.array([0.5,0.5])
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)
print(z1)
a2=np.dot(z1,W2)+b2
z2=sigmoid(a2)
print(z2)
a3=np.dot(z2,W3)+b3
y=identity_function(a3)
return y
network=init_network() #字典变量network,保存了每一层所需的参数(权重和偏置)
x=np.array([1.0,2.0])
y = forward(network, x)
print(y)
第k个神经元输出公式如下: y k = e a k ∑ i = 1 n e a i y_k=\frac{{\rm e}^{a_k}}{\sum_{i=1}^n{\rm e}^{a_i}} yk=∑i=1neaieak
a=np.array([0.3,2.9,4.0])
exp_a=np.exp(a)
print(exp_a)
sum_exp_a=np.sum(exp_a)
print(sum_exp_a)
y=exp_a/sum_exp_a
print(y)
运行结果如下:
[ 1.34985881 18.17414537 54.59815003]
74.1221542101633
[0.01821127 0.24519181 0.73659691]
定义softmax函数:
def softmax(a):
exp_a=np.exp(a)
sum_exp_a=np.sum(exp_a)
y=exp_a/sum_exp_a
return y
a = np.array([1010, 1000, 990])
y=np.exp(a) / np.sum(np.exp(a)) # softmax函数的运算
print(y) # 没有被正确计算
c = np.max(a) # 1010
c = a - c #将每个元素值减小
print(c)
y=np.exp(c) / np.sum(np.exp(c))
print(y)
运行结果如下:
[nan nan nan]
[ 0 -10 -20]
[9.99954600e-01 4.53978686e-05 2.06106005e-09]
更改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
具体实现:
a = np.array([0.3, 2.9, 4.0])
y=softmax(a)
print(y)
sum=np.sum(y)
print(sum)
运行结果如下:
[0.01821127 0.24519181 0.73659691]
1.0
y[2]=0.737(73.7%)
,概率最大,所以分类是第2个元素机器学习:分为学习和推理两个过程
学习:又称为“训练”,在这个过程中进行模型学习(使用训练数据,自动调整参数)
推理:用学到的模型对未知的数据进行推理(分类)
6
万张,测试图像有1
万张28 像素 × 28 像素
(784个像素点的灰度图像(1 通道),各个像素的取值在0 到 255
之间。每个图像数据都相应地标有“7”“2”“1”等标签
。mnist.py
,该脚本支持从下载 MNIST 数据集到将这些数据转换成 NumPy 数组等处理。jupiter notebook
中打开mnist_show.py
,并且运行,第一次运行因为调用 dataset/mnist.py
中的 load_mnist
函数会显示# coding: utf-8 # 声明编码方式为utf-8
import sys, os #引入python系统功能模块
sys.path.append(os.pardir) # #添加当前文件的上级目录的上级目录即【源代码】深度学习入门:基于Python的理论与实现到sys.path(Python 的搜索模块的路径集)
import numpy as np
from dataset.mnist import load_mnist #从dataset文件夹的mnist.py文件中添加load_mnist函数
from PIL import Image #从图像的显示 PIL(Python Image Library)模块中添加Image类
def img_show(img):
pil_img = Image.fromarray(np.uint8(img)) # 先将img转化为uint8(0-255无符号8位整型)数组,再将np.array类型的转换成PIL型数据
pil_img.show() #用PIL模块将image显示出来
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False) #将load_mnist读取出来的( 训练图像, 训练标签 ),( 测试图像, 测试标签 )形式的数据分别放到一维训练图像数组和一维测试图像数组中,且一维数组中数的大小,即图像像素是0-255
img = x_train[0] #取出第一个图像
label = t_train[0] #取出第一个图像的标签
print(label) # 5 #第一个图像是5
print(img.shape) # (784,) #第一个图像的形状(一维数组大小784大)
img = img.reshape(28, 28) # 把图像的形状变为原来的尺寸(28*28)
print(img.shape) # (28, 28)# 第一个图像表述形式变成了2维
img_show(img)
第 1 个参数 normalize 设置是否将输入图像正规化为 0.0~1.0 的值。如果将该参数设置为 False,则输入图像的像素会保持原来的 0~255
第 2 个参数 flatten 设置是否展开输入图像(变成一维数组)。如果将该参数设置为 False,则输入图像为 1 × 28 × 28 的三维数组;若设置为 True,则输入图像会保存为由 784 个元素构成的一维数组。
第 3 个参数 one_hot_label 设置是否将标签保存为one-hot表示(one-hot representation)。one-hot 表示是仅正确解标签为 1,其余皆为 0 的数组,就像 [0,0,1,0,0,0,0,0,0,0] 这样。当 one_hot_label 为 False 时,只是像 7、2 这样简单保存正确解标签;当 one_hot_label 为 True 时,标签则保存为 one-hot 表示。
调用完mnist_show.py
后,训练图像的第一张就会显示出来
import pickle #引入pickle库
sys.path.append(os.pardir)
import numpy as np
from dataset.mnist import load_mnist
from PIL import Image
def img_show(img): #图像显示函数
pil_img = Image.fromarray(np.uint8(img))
pil_img.show()
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)
img = x_train[0]
label = t_train[0]
print(label) # 5
print(img.shape) # (784,)
img = img.reshape(28, 28) # 把图像的形状变为原来的尺寸
print(img.shape) # (28, 28)
img_show(img)
def sigmoid(x): #sigmoid函数
return 1/(1+np.exp(-x))
def softmax(a): #softmax函数
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, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)
return x_test, t_test
def init_network(): #会读入保存在 pickle 文件 sample_weight.pkl 中的学习到的权重参数,因为之前我们假设学习已经完成
with open("sample_weight.pkl", 'rb') as f:
network = pickle.load(f) #将f文件中已经学习出来的权重参数放到字典变量中
return network
def predict(network, x): #mnist数据集,3层神经网络的向前传播
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) #第1层激活函数
a2 = np.dot(z1, W2) + b2
z2 = sigmoid(a2) #第2层激活函数
a3 = np.dot(z2, W3) + b3
y = softmax(a3) #输出层激活函数
return y
x, t = get_data()
network = init_network()
accuracy_cnt = 0
for i in range(len(x)):
y = predict(network, x[i])
p = np.argmax(y) # 获取概率最高的元素的索引
if p == t[i]: #索引和标签相同表示分类正确
accuracy_cnt += 1
print("Accuracy:" + str(float(accuracy_cnt) / len(x))) #计算有多少百分比的数据被正确分类
运行结果如下:
5
(784,)
(28, 28)
Accuracy:0.9352
x, t = get_data()
network = init_network()
batch_size = 100 # 批数量
accuracy_cnt = 0
for i in range(0, len(x), batch_size): #range(start, end),start-end-1列表 range(start, end, step) 跨越step大小生成列表
x_batch = x[i:i+batch_size] #从i到i+批处理数量的数据取出,即本例中x[0:100]、x[100:200]
y_batch = predict(network, x_batch)
p = np.argmax(y_batch, axis=1) #axis=1表示行方向寻找概率最大元素的索引
accuracy_cnt += np.sum(p == t[i:i+batch_size])(把批处理的所有正确找到的数的数量相加)
print(float(accuracy_cnt))
print("Accuracy:" + str(float(accuracy_cnt) / len(x)))(测试总数据总数据1万个,总共检测出9352)
运行结果如下
…
9001.0
9091.0
9172.0
9261.0
9352.0
Accuracy:0.9352
end
《陆宇杰的训练营:15天共读深度学习》 ↩︎