基本流程

加载数据 –> 训练模型找出 w,b –> 将 w,b 代入预测函数 –> 预测

实现

数据加载

数据是给好的hd5文件低像素图片

导入库 –> 加载数据集 –> 数据重塑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import numpy as np  # 导入NumPy库,用于科学计算
import h5py # 导入h5py库,用于处理HDF5文件

def load_dataset():
# 打开训练数据集文件,以只读模式读取
train_dataset = h5py.File('datasets/train_catvnoncat.h5', "r")
# 从训练数据集中提取特征数据,并转换为NumPy数组
train_set_x_orig = np.array(train_dataset["train_set_x"][:])
# 从训练数据集中提取标签数据,并转换为NumPy数组
train_set_y_orig = np.array(train_dataset["train_set_y"][:])

# 打开测试数据集文件,以只读模式读取
test_dataset = h5py.File('datasets/test_catvnoncat.h5', "r")
# 从测试数据集中提取特征数据,并转换为NumPy数组
test_set_x_orig = np.array(test_dataset["test_set_x"][:])
# 从测试数据集中提取标签数据,并转换为NumPy数组
test_set_y_orig = np.array(test_dataset["test_set_y"][:])

# 从测试数据集中提取类别信息,并转换为NumPy数组
classes = np.array(test_dataset["list_classes"][:])

# 将训练标签数据重塑为二维数组,形状为(1, 样本数量)
train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))
# 将测试标签数据重塑为二维数组,形状为(1, 样本数量)
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

我们可以模拟一个简单的 HDF5 数据集结构,并使用它来测试数据加载和处理功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import numpy as np

h5demo = {
"list_classes": [0, 1], # 类别标签
"train_set_x": [
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5]
],
"train_set_y": [0, 1, 0, 1, 0], # 训练集标签
"test_set_x": [
[5, 4, 3, 2, 1],
[5, 4, 3, 2, 1],
[5, 4, 3, 2, 1],
[5, 4, 3, 2, 1],
[5, 4, 3, 2, 1]
],
"test_set_y": [1, 0, 1, 0, 1] # 测试集标签
}


print(h5demo["list_classes"])
print(h5demo["list_classes"][:])
print(np.array(h5demo["train_set_x"][:]))
1
2
3
4
5
6
7
[0, 1]
[0, 1]
[[1 2 3 4 5]
[1 2 3 4 5]
[1 2 3 4 5]
[1 2 3 4 5]
[1 2 3 4 5]]

现在打印 train_set_x_orig 和 train_set_y_orig 的形状,观察数据的结构

1
2
3
4
5
6
7
8
# 加载数据集
train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes = load_dataset()

# 打印训练集特征数据的形状
print("train_set_x_orig shape:", train_set_x_orig.shape)

# 打印训练集标签数据的形状
print("train_set_y_orig shape:", train_set_y_orig.shape)
1
2
train_set_x_orig shape: (209, 64, 64, 3)
train_set_y_orig shape: (1, 209)
  • train_set_x_orig shape: (209, 64, 64, 3): 这表示训练集特征数据的形状。具体来说:

    • 209 是样本数量,表示有 209 张图片。

    • 64 是图片的高度和宽度,表示每张图片是 64x64 像素的正方形。

    • 3 是通道数,表示每张图片是彩色的(RGB)。

  • train_set_y_orig shape: (1, 209): 这表示训练集标签数据的形状。具体来说:

    • 1 是标签的维度,表示每个样本只有一个标签。

    • 209 是样本数量,表示每个样本对应一个标签。

解释一下维度

  • 标量: 没有维度,因为它是一个单一的数值。a=1

  • 向量: 只有一个维度,表示为一个列或行。a=[1,2,3]

  • 矩阵: 有两个维度,表示为行和列。a=[[1,2,3],[1,2,3]]

  • 张量: 有三个或更多维度,可以看作是多个矩阵的集合。a=[[[1]],[[2]],[[3]]]

1
2
3
4
5
6
7
8
9
10
scalar = np.array(1)  # 标量,0维
vector = np.array([1, 2, 3]) # 向量,1维
matrix = np.array([[1, 2, 3],[1,2,3]]) # 矩阵,2维
tensor = np.array([[[1], [2]], [[3], [4]]]) # 张量,3维

# 打印每个数组的维数
print("Scalar ndim:", scalar.ndim) # 输出: 0
print("Vector ndim:", vector.ndim) # 输出: 1
print("Matrix ndim:", matrix.ndim) # 输出: 2
print("Tensor ndim:", tensor.ndim) # 输出: 3

解释一下重塑

  • 原始的 test_set_y_orig 可能是一维数组,形状为 (样本数量,)。将其重塑为(1,样本数量)使得后续的矩阵运算更加方便和一致,尤其是在与其他二维数组(如特征矩阵)进行运算时。
    (1, 样本数量) 表示一个行向量,其中有 样本数量 个元素。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy as np

h5demo = {
"train_set_y": [0, 1, 0, 1, 0]# 训练集标签
}

train_set_y = np.array(h5demo["train_set_y"][:]) #转化nump数组

print("转换前: ")
print(train_set_y)
print(train_set_y.shape)
print(train_set_y.ndim)

print("\n换后: ")
train_set_y = train_set_y.reshape((1,train_set_y.shape[0]))
print(train_set_y)
print(train_set_y.shape)
print(train_set_y.ndim)
1
2
3
4
5
6
7
8
9
转换前: 
[0 1 0 1 0]
(5,)
1

换后:
[[0 1 0 1 0]]
(1, 5)
2

数据处理

1
2
3
4
5
6
7
8
9
m_train = train_set_x_orig.shape[0]
m_test = test_set_x_orig.shape[0]
num_px = test_set_x_orig.shape[1] # 由于我们的图片是正方形的,所以长宽相等

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

train_set_x = train_set_x_flatten/255.
test_set_x = test_set_x_flatten/255.

数据展平

操作

  • reshape(train_set_x_orig.shape[0], -1) 将每张图片展平成一个一维向量。

  • -1 表示自动计算展平后的维度。对于一张 64x64 的彩色图片,展平后会变成一个长度为 12288 的向量(64 * 64 * 3)。

  • .T 是转置操作,将数据从 (样本数量, 特征数) 转换为 (特征数, 样本数量),这在机器学习中是一个常见的格式。

为什么

  • 展平操作将每张图片的像素值展平为一个一维向量,使得每个样本都可以用一个向量表示。

  • 这种格式便于输入到机器学习模型中进行训练。

数据标准化

操作

  • 将展平后的数据除以 255,将像素值缩放到 [0, 1] 的范围内。

  • 这一步是为了加速模型的训练过程,并提高模型的稳定性。为什么标准化:

为什么

  • 标准化可以使特征具有相同的尺度,避免某些特征对模型的影响过大。

  • 通过缩放到 [0, 1],可以加速梯度下降的收敛。


模型初始化

对于线性模型,我们通常需要初始化权重和偏置。

1
2
3
4
5
6
7
def initialize_with_zeros(dim):
# 初始化权重向量w为零向量,形状为(dim, 1)
w = np.zeros((dim, 1))
# 初始化偏置b为0
b = 0
# 返回初始化的权重和偏置
return w, b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np

demo = np.zeros((2,3))
print(demo)

demo1 = np.zeros((2,1))
print(demo1)

'''
[[0. 0. 0.]
[0. 0. 0.]]
[[0.]
[0.]]
'''

前向传播和反向传播

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def propagate(w, b, X, Y):
# 获取样本数量
m = X.shape[1]

# 前向传播:计算激活值A
A = sigmoid(np.dot(w.T, X) + b)
# 计算损失函数的值,使用交叉熵损失
cost = -np.sum(Y * np.log(A) + (1 - Y) * np.log(1 - A)) / m

# 反向传播:计算梯度
dZ = A - Y
dw = np.dot(X, dZ.T) / m
db = np.sum(dZ) / m

# 将梯度存储在字典中
grads = {
"dw": dw,
"db": db
}

# 返回梯度和损失
return grads, cost

这里前向传播和反向传播直接带的公示,现在简要讲解一下原理

前向传播是指将输入数据通过神经网络传递,计算输出的过程。其主要目的是计算模型的预测值。

  1. 输入层:

    • 输入数据 XX 被传递到网络的第一层。
  2. 隐藏层(如果有):

    • 每个神经元接收输入,计算加权和,并通过激活函数得到输出。

    • 公式:a[l]=σ(W[l]a[l−1]+b[l])a[l]=σ(W[l]a[l−1]+b[l])

    • 其中,W[l]W[l] 是权重矩阵,b[l]b[l] 是偏置,σσ 是激活函数。

  3. 输出层:

    • 最后一层的输出即为模型的预测值 Y^Y^。
  4. 损失计算:

    • 计算预测值与真实值之间的差异,通常使用损失函数(如均方误差、交叉熵等)。

反向传播是指通过计算损失函数的梯度,更新模型参数的过程。其主要目的是最小化损失函数。

  1. 损失函数的梯度:

    • 计算损失函数对输出层的梯度。
  2. 链式法则:

    • 使用链式法则计算每一层的梯度。
  3. 参数更新:

    • 使用梯度下降法更新权重和偏置。

简单来说,前向传播就是输入数据,计算损失;反向传播就是根据损失,调整参数。

image-20250413135658929

模型优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost=False):
costs = [] # 用于存储每100次迭代的损失值

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

# 每100次迭代记录一次损失
if i % 100 == 0:
costs.append(cost)
if print_cost:
print("迭代的次数: %i, 误差值: %f" % (i, cost))

# 返回优化后的参数和损失
params = {
"w": w,
"b": b
}

return params, costs

模型预测函数

1
2
3
4
5
6
7
8
9
10
11
12
13
def predict(w, b, X):
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]):
# 如果激活值大于0.5,预测为1,否则为0
if A[0, i] > 0.5:
Y_prediction[0, i] = 1
else:
Y_prediction[0, i] = 0

return Y_prediction

构建和训练模型

我们将使用一个函数来整合所有步骤,包括初始化参数、优化参数、预测结果,并评估模型的性能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
def model(X_train, Y_train, X_test, Y_test, num_iterations=2000, learning_rate=0.5, print_cost=False):
'''
train_set_x 和 train_set_y: 训练集的特征和标签。
test_set_x 和 test_set_y: 测试集的特征和标签。
num_iterations: 迭代次数,决定了优化过程的持续时间。
learning_rate: 学习率,控制每次更新的步长。
print_cost: 是否打印每 100 次迭代的损失值。

'''


# 初始化参数
w, b = initialize_with_zeros(X_train.shape[0])

# 优化参数
params, costs = optimize(w, b, X_train, Y_train, num_iterations, learning_rate, print_cost)

# 从优化结果中提取参数
w = params["w"]
b = params["b"]

# 预测训练集和测试集的结果
Y_prediction_test = predict(w, b, X_test)
Y_prediction_train = predict(w, b, X_train)

# 打印训练集和测试集的准确率
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))

# 返回模型信息
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

运行模型

运行之前,看一下数据集中的图片怎么样

1
2
3
4
index = 30
plt.imshow(train_set_x_orig[index])
print ("标签为" + str(train_set_y[:, index]) + ", 这是一个'" + classes[np.squeeze(train_set_y[:, index])].decode("utf-8") + "' 图片.")
plt.show()

image-20250413135437392

1
标签为[0], 这是一个'non-cat' 图片.

也是能够正常展示

1
2
# 运行模型
d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations=2000, learning_rate=0.005, print_cost=True)

==》

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
迭代的次数: 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
训练集准确率: 99.04306220095694 %
测试集准确率: 70.0 %

我可以打印出成本的变化情况,即每次调整参数实际值与预测值的误差,应该是下降的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 从字典 d 中提取成本列表,并去除不必要的维度,就是把二维的转成一维的,便于绘图
costs = np.squeeze(d['costs'])

# 使用 Matplotlib 绘制成本随迭代次数变化的折线图
plt.plot(costs)

# 设置 y 轴标签为 'cost',表示图中每个点的 y 值代表损失函数的值
plt.ylabel('cost') # 成本

# 设置 x 轴标签为 'iterations (per hundreds)',表示图中每个点的 x 值代表迭代次数,以 100 为单位
plt.xlabel('iterations (per hundreds)') # 横坐标为训练次数,以100为单位

# 设置图表的标题,显示当前使用的学习率
plt.title("Learning rate =" + str(d["learning_rate"]))

# 显示绘制的图表
plt.show()

image-20250413140055915

接着,我们可以看看基于损失函数,学习率对模型造成的影响。(一个好的学习率,能使结果更加准确)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
learning_rates = [0.01, 0.001, 0.0001]
models = {}
for i in learning_rates:
print ("学习率为: " + str(i) + "时")
models[str(i)] = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 1500, learning_rate = i, print_cost = 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 (hundreds)')

legend = plt.legend(loc='upper center', shadow=True)
frame = legend.get_frame()
frame.set_facecolor('0.90')
plt.show()

image-20250413140441872

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
学习率为: 0.01时
训练集准确率: 99.52153110047847 %
测试集准确率: 68.0 %

-------------------------------------------------------

学习率为: 0.001时
训练集准确率: 88.99521531100478 %
测试集准确率: 64.0 %

-------------------------------------------------------

学习率为: 0.0001时
训练集准确率: 68.42105263157895 %
测试集准确率: 36.0 %

-------------------------------------------------------

这里选定学习率为 0.01

测试

通过模型训练我们找到了合适的 w,b,下一步就只需要拿这个 w,b 带入预测函数去测试图片了。

image-20250413140929607

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 读取图像文件并将其转换为 NumPy 数组
image = np.array(plt.imread(fname))

# 调整图像大小为 (num_px, num_px),并展平为一维向量
# 使用 skimage.transform 的 resize 函数,mode='reflect' 用于处理边界
my_image = tf.resize(image, (num_px, num_px), mode='reflect').reshape((1, num_px*num_px*3)).T

# 使用训练好的模型预测图像的类别,返回 0 或 1
my_predicted_image = predict(d["w"], d["b"], my_image) # 返回 0 或 1

# 判断预测结果并输出相应的文本和设置图像标题
if int(np.squeeze(my_predicted_image)) == 0:
print("预测结果为 不是猫") # 如果预测结果为 0,输出“不是猫”
plt.title("Not cat") # 设置图像标题为“不是猫”
else:
print("预测结果为 猫") # 如果预测结果为 1,输出“猫”
plt.title("Is cat") # 设置图像标题为“猫”

# 显示图像
plt.imshow(image)
plt.show()

image-20250413141423715

但是对真实图片来说,效果真的很差,可能因为数据集是像素图像,训练次数不够,并且这是一个单神经元网络。

image-20250413142543615

没办法,最后再测一下测试数据里的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 选择测试集中的一个图像索引
index = 0 # 你可以更改这个索引以选择不同的图像
# 提取图像数据
single_test_image = test_set_x[:, index].reshape((num_px, num_px, 3))
# 进行预测
single_test_image_flatten = test_set_x[:, index].reshape((num_px*num_px*3, 1))
predicted_label = predict(d["w"], d["b"], single_test_image_flatten)
# 显示图像
plt.imshow(single_test_image)
plt.title("Is cat" if int(np.squeeze(predicted_label)) == 1 else "Not cat")
plt.show()
# 输出预测结果
print("这张图的标签是 " + str(test_set_y[0, index]) + ", 预测结果是 " + ("猫" if int(np.squeeze(predicted_label)) == 1 else "不是猫"))

image-20250413143054874

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
import numpy as np
import matplotlib.pyplot as plt
import h5py
import skimage.transform as tf

def load_dataset():
train_dataset = h5py.File('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('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"][:]) # 加载标签类别数据,这里的类别只有两种,1代表有猫,0代表无猫

train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0])) # 把数组的维度从(209,)变成(1, 209),这样好方便后面进行计算
test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0])) # 从(50,)变成(1, 50)

return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes

train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()

# # 我们要清楚变量的维度,否则后面会出很多问题。下面我把他们的维度打印出来。
# print ("train_set_x_orig shape: " + str(train_set_x_orig.shape))
# print ("train_set_y shape: " + str(train_set_y.shape))
# print ("test_set_x_orig shape: " + str(test_set_x_orig.shape))
# print ("test_set_y shape: " + str(test_set_y.shape))

m_train = train_set_x_orig.shape[0]
m_test = test_set_x_orig.shape[0]
num_px = test_set_x_orig.shape[1] # 由于我们的图片是正方形的,所以长宽相等

# print ("训练样本数: m_train = " + str(m_train))
# print ("测试样本数: m_test = " + str(m_test))
# print ("每张图片的宽/高: num_px = " + str(num_px))

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.


def sigmoid(z):
s = 1 / (1 + np.exp(-z))
return s


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]

A = sigmoid(np.dot(w.T, X) + b)
cost = -np.sum(Y*np.log(A) + (1-Y)*np.log(1-A)) / m

dZ = A - Y
dw = np.dot(X, dZ.T) / m
db = np.sum(dZ) /m

grads = {
"dw":dw,
"db":db
}

return grads, cost

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:
print ("迭代的次数: %i, 误差值: %f" % (i,cost))

params = {
"w":w,
"b":b
}

return params, costs

def predict(w, b, X):
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]):
# 如果激活值大于0.5,预测为1,否则为0
if A[0, i] > 0.5:
Y_prediction[0, i] = 1
else:
Y_prediction[0, i] = 0

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])

params, costs = optimize(w, b, X_train, Y_train, num_iterations, learning_rate, print_cost)

w = params["w"]
b = params["b"]

Y_prediction_test = predict(w, b, X_test)
Y_prediction_train = predict(w, b, X_train)

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))

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


d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005, print_cost = True)



# index = 11
# plt.imshow(train_set_x_orig[index])
# print ("标签为" + str(train_set_y[:, index]) + ", 这是一个'" + classes[np.squeeze(train_set_y[:, index])].decode("utf-8") + "' 图片.")
# plt.show()





# costs = np.squeeze(d['costs'])
# plt.plot(costs)
# plt.ylabel('cost') # 成本
# plt.xlabel('iterations (per hundreds)') # 横坐标为训练次数,以100为单位
# 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 ("学习率为: " + str(i) + "时")
# models[str(i)] = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 1500, learning_rate = i, print_cost = 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 (hundreds)')

# legend = plt.legend(loc='upper center', shadow=True)
# frame = legend.get_frame()
# frame.set_facecolor('0.90')
# plt.show()


# my_image = "cat1.png"
# fname = "image/" + my_image
# image = np.array(plt.imread(fname))
# my_image = tf.resize(image,(num_px,num_px), mode='reflect').reshape((1, num_px*num_px*3)).T
# my_predicted_image = predict(d["w"], d["b"], my_image) # 返回 0 或 1

# print(my_predicted_image)
# if int(np.squeeze(my_predicted_image)) == 0:
# print("预测结果为 不是猫")
# plt.title("Not cat")
# else:
# print("预测结果为 猫")
# plt.title("Is cat")

# plt.imshow(image)
# plt.show()


# 选择测试集中的一个图像索引
index = 0 # 你可以更改这个索引以选择不同的图像
# 提取图像数据
single_test_image = test_set_x[:, index].reshape((num_px, num_px, 3))
# 进行预测
single_test_image_flatten = test_set_x[:, index].reshape((num_px*num_px*3, 1))
predicted_label = predict(d["w"], d["b"], single_test_image_flatten)
# 显示图像
plt.imshow(single_test_image)
plt.title("Is cat" if int(np.squeeze(predicted_label)) == 1 else "Not cat")
plt.show()
# 输出预测结果
print("这张图的标签是 " + str(test_set_y[0, index]) + ", 预测结果是 " + ("猫" if int(np.squeeze(predicted_label)) == 1 else "不是猫"))



'''
流程

加载数据 --> 训练模型找出 w,b --> 将 w,b 代入预测函数 --> 预测
'''

像素数据在库里。

后记

感受了一波半自动写模型,无奈菜的没边,各种问题最后都会铺面而来。

对于数据集的处理,模型逻辑代码,测试功能的编写都有待欠缺。等着下一次优化,一定能准确识别猫猫。

为了不让自己太过难堪,决定先去 py 一下别人的猫识别程序,不过他们的可能就不仅仅是猫识别了,QAQ。