吴恩达课后作业(一):具有神经网络思维的Logistic回归
·
在本文开始之前,首先声明参考了博主,本文的训练集与测试集均来自:【中文】【吴恩达课后编程作业】Course 1 - 神经网络和深度学习 - 第二周作业_吴恩达机器学习课后作业目录对应视频-CSDN博客
再结合自己对于SIgmoid函数的理解,故写下了本文的代码,故想给多方面学习Sigmoid函数的小伙伴一些小参考:
我们要做的事是搭建一个能够【识别猫】 的简单的神经网络。
在开始之前,我们有需要引入的库:
numpy :是用Python进行科学计算的基本软件包。
h5py:是与H5文件中存储的数据集进行交互的常用软件包。
lr_utils :在本文的资料包里,一个加载资料包里面的数据的简单功能的库。
import numpy as np
import h5py, copy, math
接下来是从.h5文件中读取相应的数据:
def load_dataset():
train_dataset = h5py.File('C:\\Users\\86134\\PycharmProjects\\Machine_learning\\datasets\\train_catvnoncat.h5', 'r')
train_set_x_orig = np.array(train_dataset['train_set_x'][:])
train_set_y_orig = np.array(train_dataset['train_set_y'][:])
test_dataset = h5py.File('C:\\Users\\86134\\PycharmProjects\\Machine_learning\\datasets\\test_catvnoncat.h5', 'r')
test_set_x_orig = np.array(test_dataset['test_set_x'][:])
test_set_y_orig = np.array(test_dataset['test_set_y'][:])
classes = np.array(test_dataset["list_classes"][:])
train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))
test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0]))
return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes
直接读取数据可不行,因为直接读取到的图片的维度是(209,64,64,3),如果直接对其进行运算的话不仅加大时间消耗和空间的消耗,因此还得对相应的数据进行平坦化,归一化:
#平坦图片,方便后续操作
def flatten_img(train_set_x_orig, test_set_x_orig):
#多维数组格式转换为二维矩阵格式
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
return train_set_x_flatten, test_set_x_flatten
#归一化
def normalize_img(train_set_x_flatten, test_set_x_flatten):
train_set_x = train_set_x_flatten / 255.0
test_set_x = test_set_x_flatten / 255.0
return train_set_x, test_set_x
这里解释一下为什么要对flatten之后的数据要进行转置,因为要确保我们的数据特征在行上,样本在列上。
在进行核心逻辑回归算法之前,还得对w和b进行初始化:
def initialize_parameters(dim):
#dim为维度,即输入X的维度,为w创建一个维度为(dim,1)的向量。方便后面进行矩阵计算
w = np.zeros(shape=(dim, 1))
b = 0.0
return w, b
接下来是核心的逻辑回归算法了:
sigmoid公式:
def sigmoid(z):
return 1.0 / (1.0 + np.exp(-z))
计算sigmoid的损失值:
def compute_cost_sigmoid(X, y, w, b):
m = X.shape[1] #样本数量
# for i in range(m):
# z_i = np.dot(X, w) + b
# f_wb_i = sigmoid(z_i)
# cost += -y[i] * np.log(f_wb_i) - (1 - y[i]) * np.log(1 - f_wb_i)
#
# cost /= m
A = sigmoid(np.dot(w.T, X) + b)
cost = (-1.0 / m) * np.sum(y * np.log(A) + (1 - y) * np.log(1 - A))
return cost
这里保留了使用最原始的循环计算,但是效率不高,后面改成了使用向量来直接计算,下面计算梯度也是一样。
计算sigmoid的梯度:
def compute_sigmoid_descent(X, y, w, b):
# 获取X的行数和列数
# m, n = X.shape
# dj_dw = np.zeros((n, ))
# dj_db = 0.0
#
# for i in range(m):
# z_i = np.dot(X[i], w) + b
# f_wb_i = sigmoid(z_i)
# err_i = f_wb_i - y[i] #与目标值的误差
#
# for j in range(n):
# dj_dw[j] = dj_dw[j] + err_i * X[i, j] # #计算代价函数对每个权重参数 w_j 的偏导数(梯度)的累加值。
# dj_db += err_i
# dj_dw /= m
# dj_db /= m
n, m = X.shape #n为特征数量, m为样本数量
A = sigmoid(np.dot(w.T, X) + b)
dz = A - y
dj_dw = (1.0 / m) * np.dot(X, dz.T)
dj_db = (1.0 / m) * np.sum(dz)
return dj_dw, dj_db
接下来是计算梯度更新了:
def gradient_descent(X, y, w_in, b_in, learning_rate, num_iterations):
j_history = []
w = copy.deepcopy(w_in)
b = b_in
for i in range(num_iterations):
#计算当前的梯度并且更新参数
dj_dw, dj_db = compute_sigmoid_descent(X, y, w, b)
#更新
w = w - learning_rate * dj_dw
b = b - learning_rate * dj_db
#保存当前损失值
if i < 10000:
j_history.append(compute_cost_sigmoid(X, y, w, b))
#输出
if i % math.ceil(num_iterations / 10) == 0:
print(f"Iteration {i:4d}: Cost {j_history[-1]} ")
return w, b, j_history
这里还得实现预测函数,用来判断对应的图片是否是猫:
def predict(X, w, b):
m = X.shape[1] #图片的数量
Y_prediction = np.zeros((1, m))
#计算猫在图片中出现的概率
A = sigmoid(np.dot(w.T, X) + b)
for i in range(A.shape[1]):
#将概率a[0, i]转换为实际预测p[0, i]
Y_prediction[0, i] = 1 if A[0, i] > 0.5 else 0
return Y_prediction
最后整合一下以上所有的函数,不然全写在main里面显得太乱,观感不好:
def model(X_train, Y_train, X_test, Y_test, learning_rate, num_iterations):
w_init, b_init = initialize_parameters(X_train.shape[0])
w, b, costs = gradient_descent(X_train, Y_train, w_init, b_init, learning_rate, num_iterations)
#进行猫预测
Y_prediction_train = predict(X_train, w, b)
Y_prediction_test = predict(X_test, w, b)
# 打印训练后的准确性
print("训练集准确性:", format(100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100), "%")
print("测试集准确性:", format(100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100), "%")
params = {
"costs": costs,
"Y_prediction_train": Y_prediction_train,
"Y_prediction_test": Y_prediction_test,
"learning_rate": learning_rate,
"num_iterations": num_iterations,
"w" : w,
"b" : b
}
return params
最后运行的结果为:

一下是完整的代码:
import numpy as np
import h5py, copy, math
#读取数据
def load_dataset():
train_dataset = h5py.File('C:\\Users\\86134\\PycharmProjects\\Machine_learning\\datasets\\train_catvnoncat.h5', 'r')
train_set_x_orig = np.array(train_dataset['train_set_x'][:])
train_set_y_orig = np.array(train_dataset['train_set_y'][:])
test_dataset = h5py.File('C:\\Users\\86134\\PycharmProjects\\Machine_learning\\datasets\\test_catvnoncat.h5', 'r')
test_set_x_orig = np.array(test_dataset['test_set_x'][:])
test_set_y_orig = np.array(test_dataset['test_set_y'][:])
classes = np.array(test_dataset["list_classes"][:])
train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))
test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0]))
return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes
#平坦图片,方便后续操作
def flatten_img(train_set_x_orig, test_set_x_orig):
#多维数组格式转换为二维矩阵格式
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
return train_set_x_flatten, test_set_x_flatten
#归一化
def normalize_img(train_set_x_flatten, test_set_x_flatten):
train_set_x = train_set_x_flatten / 255.0
test_set_x = test_set_x_flatten / 255.0
return train_set_x, test_set_x
"""
接下来是核心逻辑回归算法
"""
def sigmoid(z):
return 1.0 / (1.0 + np.exp(-z))
def initialize_parameters(dim):
#dim为维度,即输入X的维度,为w创建一个维度为(dim,1)的向量。方便后面进行矩阵计算
w = np.zeros(shape=(dim, 1))
b = 0.0
return w, b
#计算sigmoid的损失值
def compute_cost_sigmoid(X, y, w, b):
m = X.shape[1] #样本数量
# for i in range(m):
# z_i = np.dot(X, w) + b
# f_wb_i = sigmoid(z_i)
# cost += -y[i] * np.log(f_wb_i) - (1 - y[i]) * np.log(1 - f_wb_i)
#
# cost /= m
A = sigmoid(np.dot(w.T, X) + b)
cost = (-1.0 / m) * np.sum(y * np.log(A) + (1 - y) * np.log(1 - A))
return cost
#计算sigmoid的梯度
def compute_sigmoid_descent(X, y, w, b):
# 获取X的行数和列数
# m, n = X.shape
# dj_dw = np.zeros((n, ))
# dj_db = 0.0
#
# for i in range(m):
# z_i = np.dot(X[i], w) + b
# f_wb_i = sigmoid(z_i)
# err_i = f_wb_i - y[i] #与目标值的误差
#
# for j in range(n):
# dj_dw[j] = dj_dw[j] + err_i * X[i, j] # #计算代价函数对每个权重参数 w_j 的偏导数(梯度)的累加值。
# dj_db += err_i
# dj_dw /= m
# dj_db /= m
n, m = X.shape #n为特征数量, m为样本数量
A = sigmoid(np.dot(w.T, X) + b)
dz = A - y
dj_dw = (1.0 / m) * np.dot(X, dz.T)
dj_db = (1.0 / m) * np.sum(dz)
return dj_dw, dj_db
#梯度下降
def gradient_descent(X, y, w_in, b_in, learning_rate, num_iterations):
j_history = []
w = copy.deepcopy(w_in)
b = b_in
for i in range(num_iterations):
#计算当前的梯度并且更新参数
dj_dw, dj_db = compute_sigmoid_descent(X, y, w, b)
#更新
w = w - learning_rate * dj_dw
b = b - learning_rate * dj_db
#保存当前损失值
if i < 10000:
j_history.append(compute_cost_sigmoid(X, y, w, b))
#输出
if i % math.ceil(num_iterations / 10) == 0:
print(f"Iteration {i:4d}: Cost {j_history[-1]} ")
return w, b, j_history
#实现预测函数
def predict(X, w, b):
m = X.shape[1] #图片的数量
Y_prediction = np.zeros((1, m))
#计算猫在图片中出现的概率
A = sigmoid(np.dot(w.T, X) + b)
for i in range(A.shape[1]):
#将概率a[0, i]转换为实际预测p[0, i]
Y_prediction[0, i] = 1 if A[0, i] > 0.5 else 0
return Y_prediction
#整合函数
def model(X_train, Y_train, X_test, Y_test, learning_rate, num_iterations):
w_init, b_init = initialize_parameters(X_train.shape[0])
w, b, costs = gradient_descent(X_train, Y_train, w_init, b_init, learning_rate, num_iterations)
#进行猫预测
Y_prediction_train = predict(X_train, w, b)
Y_prediction_test = predict(X_test, w, b)
# 打印训练后的准确性
print("训练集准确性:", format(100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100), "%")
print("测试集准确性:", format(100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100), "%")
params = {
"costs": costs,
"Y_prediction_train": Y_prediction_train,
"Y_prediction_test": Y_prediction_test,
"learning_rate": learning_rate,
"num_iterations": num_iterations,
"w" : w,
"b" : b
}
return params
if __name__ == '__main__':
learning_rate = 0.01
num_iterations = 2000
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset() #加载数据
train_set_x_flatten, test_set_x_flatten = flatten_img(train_set_x_orig, test_set_x_orig) #平坦数据
train_set_x, test_set_x = normalize_img(train_set_x_flatten, test_set_x_flatten) #归一化数据
params = model(train_set_x, train_set_y, test_set_x, test_set_y, learning_rate, num_iterations)更多推荐
所有评论(0)