这是我做的第一道神经网络的编程题,使用python3.8,jupyter notebook。
这道题的目的就是神经网络思维的入门,小试牛刀。
在开始之前需要先准备测试数据文件和工具类
链接:https://pan.baidu.com/s/1uX9_MTnaHB8HHdHneOMz3Q 密码:8p3h

datasets 是测试数据,lr_utils是解析图片数据的工具。
然后安装h5py和matplotlib库,numpy库如果没有也需要安装。
测试数据解包含209张图片(其中72张是猫,137张不是猫)的数据,以.h5作为尾缀,这种格式的数据,特意去搜了一下,是一种高效数据存储格式。https://www.hdfgroup.org/solutions/hdf5/
下面直接上代码
import numpy as np
import matplotlib.pyplot as plt
import h5py
from lr_utils import load_dataset
# 导入数据集中的训练数据和测试数据
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()
# 对数据集进行降维处理,告诉reshape函数将数据分城209份,每份为1行,然后再用T函数转置,结果为209列,12288行。每列为一个样本
train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1).T
test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1).T
# 对像素数据进行标准化处理,像素数据不会比255大,处理之后数据位于0-1之间
train_set_x = train_set_x_flatten / 255
test_set_x = test_set_x_flatten / 255
#构造sigmod函数
def sigmoid(z):
s = 1 / (1 + np.exp(-z))
return s
#初始化参数 w b
def initialize_with_zeros(dim):
w = np.zeros((dim,1))
b = 0
return (w, b)
#构造传播函数,用于计算损失函数和梯度
def propagate(w, b, X, Y):
m = X.shape[1]
z = np.dot(w.T, X) + b
A = sigmoid(z)
#计算成本
cost = (-1 / m) * np.sum(Y * np.log(A) + (1 - Y) * (np.log(1 - A)))
dw = (1 / m) * np.dot(X, (A - Y).T)
db = (1 / m) * np.sum(A - Y)
assert(dw.shape == w.shape)
assert(db.dtype == float)
cost = np.squeeze(cost)
assert(cost.shape == ())
grads = {
"dw" : dw,
"db" : db
}
return (grads, cost)
#构造优化函数,目标是通过最小化损失函数J来学习w和b,对于参数θ,更新规则是θ=θ-αdθ,其中α是学习率
def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):
costs = []
for i in range(num_iterations):
grads, cost = propagate(w, b, X, Y)
dw = grads['dw']
db = grads['db']
# 从第二次循环开始,w b会减少
w = w - learning_rate * dw
b = b - learning_rate * db
if i % 100 == 0:
costs.append(cost)
if print_cost and (i % 100 == 0):
print("迭代的次数: %i, 误差值: %f" %(i, cost))
params = {"w": w, "b": b}
grads = {"dw": dw, "db": db}
return params, grads, costs
def predict(w, b, X):
m = X.shape[1]
Y_prediction = np.zeros((1, m))
w = w.reshape(X.shape[0], 1)
A = sigmoid(np.dot(w.T, X) + b)
for i in range(A.shape[1]):
Y_prediction[0, i] = 0 if A[0, i] <= 0.5 else 1
assert(Y_prediction.shape == (1, m))
return Y_prediction
#把所有的函数整合到一个model中
def model(X_train, Y_train, X_test, Y_test, num_iterations = 2000, learning_rate = 0.5, print_cost = False):
w, b = initialize_with_zeros(X_train.shape[0])
parameters, grads, costs = optimize(w, b, X_train, Y_train, num_iterations, learning_rate, print_cost)
w = parameters["w"]
b = parameters["b"]
Y_prediction_test = predict(w, b, X_test)
Y_prediction_train = predict(w, b, X_train)
print("train accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100))
print("test accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100))
d = {"costs": costs,
"Y_prediction_test": Y_prediction_test,
"Y_prediction_train": Y_prediction_train,
"w": w,
"b": b,
"learning_rate": learning_rate,
"num_iterations": num_iterations }
return d
#运行单元训练模型
print("====================测试model====================")
d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005, print_cost = True)
#绘制图片
costs = np.squeeze(d["costs"])
plt.plot(costs)
plt.ylabel("cost")
plt.xlabel("iterations (per hundreds)")
plt.title("Learning rate = " + str(d["learning_rate"]))
plt.show()
输出结果
====================测试model====================
迭代的次数: 0, 误差值: 0.693147
迭代的次数: 100, 误差值: 0.584508
迭代的次数: 200, 误差值: 0.466949
迭代的次数: 300, 误差值: 0.376007
迭代的次数: 400, 误差值: 0.331463
迭代的次数: 500, 误差值: 0.303273
迭代的次数: 600, 误差值: 0.279880
迭代的次数: 700, 误差值: 0.260042
迭代的次数: 800, 误差值: 0.242941
迭代的次数: 900, 误差值: 0.228004
迭代的次数: 1000, 误差值: 0.214820
迭代的次数: 1100, 误差值: 0.203078
迭代的次数: 1200, 误差值: 0.192544
迭代的次数: 1300, 误差值: 0.183033
迭代的次数: 1400, 误差值: 0.174399
迭代的次数: 1500, 误差值: 0.166521
迭代的次数: 1600, 误差值: 0.159305
迭代的次数: 1700, 误差值: 0.152667
迭代的次数: 1800, 误差值: 0.146542
迭代的次数: 1900, 误差值: 0.140872
train accuracy: 99.04306220095694 %
test accuracy: 70.0 %
损失曲线

代码编写参考了以下两位博主的文章,在此感谢他们的无私奉献。
https://blog.csdn.net/u013733326/article/details/79639509
https://www.kesci.com/home/project/5dd23dbf00b0b900365ecef1
在编写代码途中遇到了很多bug和不懂的问题,现在记录一下。
1.为什么激活函数sigmoid按照0-0.5,0.5-1进行分类,而不是0-0.8,0.8-1进行分类?
因为这是入门的编程题,所以暂时取0.5运行计算,在实际应用中,需要根本样本的实际情况取值,出学不必深究。
2.为什么将0.5-1的数据认定是猫?
因为在损失函数中,预测的y值和实际的y值接近的时候,损失函数值最小,本次样本是猫的时候标签值为1,不是猫的标签值为0,随着损失函数越来越小,说明预测的y值更接近1,所以靠近1的一类认为是猫
网友评论