目录
1. Activation Function
step function
sigmoid function
ReLU
2. 多维数组的运算
多维数组
矩阵乘法
神经网络的内积
3. 三层神经网络的实现
问题
各层信号传递的实现
4. 输出层的设计
softmax
5. 手写数字识别
MNIST数据集
神经网络的推理处理
批处理(batch)
激活函数会将输入信号的总和转换为输出信号
阶跃函数:以阈值为界,一旦输入超过阈值,就切换输出
简单实现
def step_function1(x):
if x > 0:
return 1
else:
return 0
# 如上简单的实现不允许参数取NumPy数组,考虑下述实现
def step_function2(x):
y = x > 0
return y.astype(np.int)
# 再简化
def step_function(x):
return (x > 0).astype(np.int)
图形
x = np.arange(-5.0, 5.0, 0.1)
y = step_function(x)
plt.plot(x, y)
plt.ylim(-0.1, 1.1) # 指定y轴的范围
plt.show()
实现
def sigmoid(x):
return 1 / (1 + np.exp(-x))
图形
x = np.arange(-5.0, 5.0, 0.1)
y = sigmoid(x)
plt.plot(x, y)
plt.ylim(-0.1, 1.1) # 指定y轴的范围
plt.show()
实现
def relu(x):
return np.maximum(0, x)
图形
x = np.arange(-5.0, 5.0, 0.1)
y = relu(x)
plt.plot(x, y)
plt.ylim(-0.1, 1.1) # 指定y轴的范围
plt.show()
# 一维数组
>>>A = np.array([1, 2, 3, 4])
>>>print(A)
[1 2 3 4]
>>>np.ndim(A) # 获取数组的维数
1
>>>A.shape # 获取数组的形状,返回结果是一个元组
(4,)
>>>A.shape[0] # 获取指定内容
4
# 二维数组
>>>B = np.array([[1, 2], [3, 4], [5, 6]])
>>>print(B)
[[1 2]
[3 4]
[5 6]]
>>>np.ndim(B)
2
>>>B.shape
(3, 2)
>>>A = np.array([[1, 2], [3, 4]])
>>>A.shape
(2, 2)
>>>B = np.array([[5, 6], [7, 8]])
>>>B.shape
(2, 2)
>>>np.dot(A, B)
array([[19, 22],
[43, 50]])
# 从输入层到第1层
X = np.array([1.0, 0.5])
W1 = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
B1 = np.array([0.1, 0.2, 0.3])
A1 = np.dot(X, W1) + B1
# 使用sigmoid函数
Z1 = sigmoid(A1)
# 从第1层到第2层
W2 = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
B2 = np.array([0.1, 0.2])
A2 = np.dot(Z1, W2) + B2
Z2 = sigmoid(A2)
# 第2层到输出层
# 输出层的激活函数用σ()表示
# 一般的,回归问题用恒等函数,二元分类用sigmoid函数,多元分类用softmax函数
# 恒等函数:将输入按原样输出
def identity_function(x):
return x
W3 = np.array([[0.1, 0.3], [0.2, 0.4]])
B3 = np.array([0.1, 0.2])
A3 = np.dot(Z2, W3) + B3
Y = identity_function(A3)
代码结构优化
import numpy as np
# 进行权重和偏置的初始化,并将它们保存在字典变量network中
# 该字典变量中保存了每一层所需的参数(权重和偏置)
from torch import softmax
from ch3_NeuralNetworks.SigmoidFunction import sigmoid
from ch3_NeuralNetworks.three_layer_NN1 import identity_function
def init_network():
network = {}
network['W1'] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
network['b1'] = np.array([0.1, 0.2, 0.3])
network['W2'] = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
network['b2'] = np.array([0.1, 0.2])
network['W3'] = np.array([[0.1, 0.3], [0.2, 0.4]])
network['b3'] = np.array([0.1, 0.2])
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)
a2 = np.dot(z1, W2) + b2
z2 = sigmoid(a2)
a3 = np.dot(z2, W3) + b3
y = identity_function(a3)
return y
network = init_network()
x = np.array([1.0, 0.5])
y = forward(network, x)
print(y)
神经网络可以用在分类问题和回归问题上,不过需要根据情况改变输出层的激活函数。一般而言,回归问题用恒等函数,分类问题用softmax函数
恒等函数
softmax函数
import numpy as np
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
import sys
import os
import numpy as np
from PIL import Image
sys.path.append(os.pardir)
from mnist import load_mnist
# 载入数据集
# (训练图象,训练标签),(测试图象,测试标签)
# flatten : 是否将图像展开为一维数组
# normalize : 将图像的像素值正规化为0.0~1.0,否则保持0~255
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)
# 输出各个数据的形状
print(x_train.shape, t_train.shape, x_test.shape, t_test.shape)
# 显示第一张图片
def img_show(img):
pil_img = Image.fromarray(np.uint8(img))
pil_img.show()
img = x_train[0]
label = t_train[0]
print(label)
print(img.shape)
img = img.reshape(28, 28) # 把图象的形状变成原来的尺寸
print(img.shape)
img_show(img)
输入层有784个神经元(图像大小为28*28)
输出层有10个神经元(数字0-9)
有两个隐藏层,第一个隐藏层有50个神经元,第二个隐藏层有100个神经元(可以为任意值)
用以下3个函数来实现神经网络的推断处理(假设上述学习已完成)
get_data()
def get_data():
(x_train, t_train), (x_test, t_test) = \\
load_mnist(flatten=True, normalize=False, one_hot_label=False)
return x_test, t_test
init_network()
def init_network():
with open("sample_weight.pkl", 'rb') as f:
network = pickle.load(f)
return network
predict()
def predict(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)
a2 = np.dot(z1, W2) + b2
z2 = sigmoid(a2)
a3 = np.dot(z2, W3) + b3
y = softmax(a3)
return y
识别精度:即能在多大程度上正确分类
# 首先获得MNIST数据集,然后生成网络
x, t = get_data()
network = init_network()
# 用for语句逐一取出保存在x中的图像数据,用predict进行分类
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)))
正规化(normalization):把数据限定到某个范围内的处理
预处理(pre-processing):对神经网络的输入数据进行某种既定的转换
打包式输入数据称为批(batch)
# 加粗部分是与之前的实现的不同之处
x, t = get_data()
network = init_network()
**# 一次输入100个数据**
**batch_size = 100 # 批数量**
accuracy_cnt = 0
**# i=0,100,200......**
**for i in range(0, len(x), batch_size):
# 切片取出批数据
x_batch = x[i:i+batch_size]
y_batch = predict(network, x_batch)
# 给定参数axis=1,表示指定在y_batch这个100*10的数组中
# 沿第1维方向找到值最大的元素的索引(第0维为列方向,第1维为行方向)
p = np.argmax(y_batch, axis=1)
# ‘p == t[i:i+batch_size]’ 得到一个布尔型数组,通过sum()得到值为True的个数
accuracy_cnt += np.sum(p == t[i:i+batch_size])**
print("Accuracy:" + str(float(accuracy_cnt) / len(x)))