略去一些有关神经网络和激活函数的相关概念,本人在读这本书的时候已有一定的基础。
简单的阶跃函数的实现
def step_function(x):
if x > 0:
return 1
else:
return 0
显然上述函数不能接受形如np.array数组作为参数,需加以改造
def step_function(x):
x = x > 0
return x.astype(np.int)
x=np.array([-2,1,3,-9])
print(step_function(x))
print(x)
[0 1 1 0]
[-2 1 3 -9]
一步步看这个函数做了什么
x=np.array([-2,1,3,-9])
x=x>0
print(x)
x=x.astype(np.int)
print(x)
[False True True False]
[0 1 1 0]
画一个阶跃函数的图形
def step_function(x):
return (x > 0).astype(np.int)
#return np.array(x>0, dtype=np.int) 这样写也可以
x = np.arange(-5, 5, 0.1)
y = step_function(x)
plt.xlabel('x')
plt.ylabel('y')
plt.title('step_function')
plt.ylim(-0.1, 1.1)
plt.plot(x, y)
plt.show()
阶跃函数
sigmoid函数实现并绘制
def sigmoid(x):
return 1.0 / (1 + np.exp(-x))
y1 = step_function(x)
y2 = sigmoid(x)
plt.xlabel('x')
plt.ylabel('y')
plt.title('sigmoid & step')
plt.ylim(-0.1, 1.1)
plt.plot(x, y1,label='step',linestyle='--')
plt.plot(x, y2,label='sigmoid')
plt.show()
sigmoid函数
ReLU函数是近年来的常用激活函数
def ReLU(x):
#np.maximum函数会从输入的数值中选择较大的那个值进行输出
return np.maximum(0,x)
y=ReLU(x)
plt.plot(x,y)
plt.show()
ReLU函数
有关多维数组的基本概念
A = np.array([1, 2, 3, 4, 5])
B = np.array([[5, 6], [7, 7], [9, 0]])
print(A.shape) #返回一个元组
print(np.ndim(A)) #获取A的维度
print(A.shape[0])
print(np.ndim(B))
print(B.shape[1]) #查看元组的第二个元素
(5,)
1
5
2
2
有关矩阵乘法
C = np.array([[3, 1, 1], [5, 6, 7]])
print(C.shape)
print(np.dot(B, C))
print(np.dot(C, B))
(2, 3)
[[45 41 47]
[56 49 56]
[27 9 9]]
[[ 31 25]
[130 72]]
实现一个如下图所示三层神经网络
3层神经网络:输入层(第0层)有2个神经元,第1个隐藏层(第1层)有3个神经元,第2个隐藏层(第2层)有2个神经元,输出层(第3层)有2个神经元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
Z1 = sigmoid(A1)
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)
W3 = np.array([[0.1, 0.3], [0.2, 0.4]])
B3 = np.array([0.1, 0.2])
A3 = np.dot(Z2, W3) + B3 #这个例子A3即为输出
print(A3)
[0.31682708 0.69627909]
整理代码,只把权重记为大写字母,偏置量或中间结果用小写字母表示
def identity_function(x): #将“恒等函数”作为输出层的激活函数
return x
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)
[0.31682708 0.69627909]
之前用了恒等函数作为输出层的激活函数,现在看一下另一种函数——softmax
def softmax(y):
exp_y = np.exp(y)
exp_sum = np.sum(exp_y)
return exp_y / exp_sum
a = np.array([0.3, 2.9, 4.0])
print(softmax(a))
[0.01821127 0.24519181 0.73659691]
softmax的指数运算可能发生数据溢出,可改进如下
def softmax(y):
c = np.max(y)
exp_y = np.exp(y - c)
exp_sum = np.sum(exp_y)
return exp_y / exp_sum
手写体识别数据集mnist
#我将本程序与mmnis.py放入同一文件夹内
from mnist import load_mnist
#flatten为True意味着28*28的图像展开为一维数组,为False则输入图像为1×28×28的三维数组
(x_train, y_train), (x_test, y_test) = load_mnist(
flatten=True, normalize=False)
print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)
(60000, 784)
(60000,)
(10000, 784)
(10000,)
显示数据集的第一张图片
from PIL import Image
def img_show(img):
#把numpy数组的图像数据转换为PIL用的数据对象
pil_img = Image.fromarray(np.uint8(img))
pil_img.show()
img = x_train[0]
label = y_train[0]
print(label)
print(img.shape)
img = img.reshape(28, 28)
print(img.shape)
img_show(img)
5
(784,)
(28, 28)
我们假设已经完成模型的训练,参数存储在sample_weight.pkl这个随书附赠的文件中,我们直接调用这个文件
import pickle
def get_data():
(x_train, y_train), (x_test, y_test) = load_mnist(
flatten=True, normalize=True, one_hot_label=False)
return x_test, y_test
def init_network():
f = open('sample_weight.pkl', 'rb')
network = pickle.load(f)
return network
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
查看模型准确率
x, y = get_data()
network = init_network()
acc_cnt = 0
y_pred = predict(network, x)
print(y_pred.shape)
y_pred = np.argmax(y_pred, axis=1) #获取每一行的最大值索引
print('图像识别成功率' + str(np.sum(np.array(y_pred == y, dtype=np.int)) / len(y)))
(10000, 10)
图像识别成功率0.9352
批处理在后续参数调优时有重大意义,这里简单介绍一下批处理
x, y = get_data()
network = init_network()
batch_size = 100 #一次批量处理100张图片
acc_cnt=0
for i in range(0,len(x),batch_size):
x_batch = x[i:i+batch_size]
y_batch = predict(network,x_batch)
p=np.argmax(y_batch,axis=1)
acc_cnt += np.sum(p==y[i:i+batch_size])
print('图像识别成功率:' + str(acc_cnt / len(x)))
图像识别成功率:0.9352
网友评论