【Deep Learning】L1W2作业
本文为吴恩达 Deep Learning 作业,逻辑回归分类器,识别猫
获得数据
H5 文件:
- H5 文件是层次数据格式第5代的版本 (Hierarchical Data Format, HDF5),它是用于存储科学数据的一种文件格式和库文件。
- H5 将文件结构简化成两个主要的对象类型:
- 数据集 (dataset):同一类型数据的多维数组。
- 组 (group):一种容器结构,可以包含数据集和其他组,若一个文件中存放了不同种类的数据集,这些数据集的管理就用到了组。
读取 H5 格式数据集:
def load_dataset():
train_dataset = h5py.File('train_catvnoncat.h5', "r")
train_set_x_orig = np.array(train_dataset["train_set_x"][:]) # features
train_set_y_orig = np.array(train_dataset["train_set_y"][:]) # labels
test_dataset = h5py.File('test_catvnoncat.h5', "r")
test_set_x_orig = np.array(test_dataset["test_set_x"][:]) # features
test_set_y_orig = np.array(test_dataset["test_set_y"][:]) # labels
classes = np.array(test_dataset["list_classes"][:]) # 让 labels 人类可读, 或许
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
查看图片:
set_y
是train_set_y
或test_set_y
,是 \(1\) 行 \(m\) 列的数组 (\(m\) 是样本数量),其中元素的值为 \(0\) 或 \(1\),可以通过classes
映射成cat
或non-cat
。
def show_one(set_x_orig, set_y, classes, index):
plt.imshow(set_x_orig[index])
plt.show()
print("y = " + str(set_y[:, index]) + ", it's a '"
+ classes[np.squeeze(set_y[:, index])].decode("utf-8") + "' picture.")
查看数据信息:
train_set_x_orig
的维度为(m_train,num_px,num_px,3)
。train_set_y
的维度为(1, m_train)
。
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()
show_one(test_set_x_orig, test_set_y, classes, 5)
show_one(train_set_x_orig, train_set_y, classes, 3)
m_train = train_set_x_orig.shape[0] # 训练集示例数量
m_test = test_set_x_orig.shape[0] # 测试集示例数量
num_px = train_set_x_orig.shape[1] # 训练图像的高度 = 训练图像的宽度
预处理
重塑矩阵:
- 将维度为
(num_px,num_px,3)
的图片重塑为(num_px * amp_px * 3, 1)
。
train_set_x_flatten = train_set_x_orig.reshape(m_train, -1).T
test_set_x_flatten = test_set_x_orig.reshape(m_test, -1).T
标准化数据:
train_set_x = train_set_x_flatten / 255.
test_set_x = test_set_x_flatten / 255.
\(sigmoid\) 函数:
def sigmoid(z):
s = 1 / (1 + np.exp(-z))
return s
主要算法
初始化
- \(w\) 为 \(n\) 行 \(1\) 列零向量(
train_set_x
也是 \(n\) 行 \(1\) 列向量),\(b\) 为零。
# 将 w 初始化为 dim 维列向量, 将 b 初始化为 0
def initialize_with_zeros(dim):
w = np.zeros((dim, 1))
b = 0
assert (w.shape == (dim, 1))
assert (isinstance(b, float) or isinstance(b, int))
return w, b
向前传播与计算代价
- 依据《向量化逻辑回归的梯度下降结果》这一节的伪代码:
# 梯度 grads, 损失函数 cost
# 输入 X, 输出 Y, 参数 w, b, 中间变量 A, Z, 训练集数量 m
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))
dz = A - Y
dw = 1 / m * np.dot(X, dz.T)
db = 1 / m * np.sum(dz)
assert (dw.shape == w.shape)
assert (db.dtype == float)
cost = np.squeeze(cost)
assert (cost.shape == ())
grads = {"dw": dw, "db": db}
return grads, cost
反向传播与更新
um_iterations
是迭代次数,learning_rate
是学习因子。- 使用梯度下降法,通过训练集学习 \(w\) 和 \(b\)。
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 = w - learning_rate * dw
b = b - learning_rate * db
if i % 100 == 0:
costs.append(cost)
if print_cost and i % 100 == 0:
print("Cost after iteration %i: %f" % (i, cost))
params = {"w": w, "b": b}
grads = {"dw": dw, "db": db}
return params, grads, costs
结果
预测
- 预测测试集的结果,\(w\) 和 \(b\) 由训练集学习得到,\(X\) 是测试集。
def predict(w, b, X):
m = X.shape[1]
w = w.reshape(X.shape[0], 1)
A = sigmoid(np.dot(w.T, X) + b)
Y_prediction = (A > 0.5)
assert (Y_prediction.shape == (1, m))
return Y_prediction
整合
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
main 函数
def main():
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()
# train_set_x_orig 的维度为 (m_train,num_px,num_px,3)
# train_set_y 的维度为 (1, m_train)
m_train = train_set_x_orig.shape[0] # 训练集示例数量
m_test = test_set_x_orig.shape[0] # 测试集示例数量
num_px = train_set_x_orig.shape[1] # 训练图像的高度 = 训练图像的宽度
# 重塑矩阵
# 将维度为 (num_px,num_px,3) 的图片重塑为 (num_px * amp_px * 3, 1)
train_set_x_flatten = train_set_x_orig.reshape(m_train, -1).T
test_set_x_flatten = test_set_x_orig.reshape(m_test, -1).T
# 对数据集进行居中和标准化, 暂且简单的除以 255
train_set_x = train_set_x_flatten / 255.
test_set_x = test_set_x_flatten / 255.
# 训练与测试
d = model(train_set_x, train_set_y, test_set_x, test_set_y, 2000, 0.005, False)
# 绘制图像
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()
拓展
学习因子的选择
learning_rates = [0.01, 0.001, 0.0001]
models = {}
for i in learning_rates:
print("learning rate is: " + str(i))
models[str(i)] = model(train_set_x, train_set_y, test_set_x, test_set_y, 1500, i, False)
print('\n' + "-------------------------------------------------------" + '\n')
for i in learning_rates:
plt.plot(np.squeeze(models[str(i)]["costs"]), label=str(models[str(i)]["learning_rate"]))
plt.ylabel('cost')
plt.xlabel('iterations')
legend = plt.legend(loc='upper right', shadow=True)
frame = legend.get_frame()
frame.set_facecolor('0.90')
plt.show()
使用自己的图像
image = np.array(plt.imread('cat_in_iran.jpg'))
my_image = np.array(Image.fromarray(image).resize((num_px, num_px))).reshape((1, num_px * num_px * 3)).T
my_predicted_image = predict(d["w"], d["b"], my_image)
plt.imshow(image)
print("y = " + str(np.squeeze(my_predicted_image)) + ", your algorithm predicts a \"" +
classes[int(np.squeeze(my_predicted_image)), ].decode("utf-8") + "\" picture.")
使用 sklearn
- 结果不好, 不会搞,咕咕咕~。
clf = LogisticRegressionCV(max_iter=2000, penalty='l1', solver='liblinear', tol=0.005)
clf.fit(train_set_x.T, np.ravel(train_set_y.T))
LR_predictions = clf.predict(train_set_x.T)
print("train accuracy: {} %".
format(100 - np.mean(np.abs(LR_predictions - train_set_y.T)) * 100))
关于 Python
plt
plt.legend
:
- 设置图例,咕咕咕~。
np
np.squeeze
:
- 改变数组的维数,把维度为 1 的删去。
np.zeros
:
w = np.zeros((dim, 1))
创建维度为(dim, 1)
的零向量。
np.random.rand(d0, d1, d2, ......, dn)
:
- 创建维度为
(d0, d1, d2, ......, dn)
的随机向量,取值在 \([0, 1)\)。
np.random.randn(d0, d1, d2, ......, dn)
:
- 创建维度为
(d0, d1, d2, ......, dn)
的随机向量,服从标准正态分布。
np.mean
:
- 计算算术平均值。