这是我的第一个人工智能程序,最终目的是判断图片里有没有海绵宝宝
从最开始的数据获取、数据集制作、模型建立都是我一手包办
我是看床长的人工智能教程学的,本程序仅供参考,禁止挪用来做奇怪的事
如果喜欢,请去找床长的人工智能教程学习
数据获取:python:从零开始的百度图片爬虫
数据集制作:python:从零开始的图片h5py数据集制作
千里之行始于足下 !
纸上得来终觉浅 !
绝知此事要躬行 !!
数据集加载
import numpy as np
import h5py
import matplotlib.pyplot as plt
import skimage.transform as tf
数据集我直接用之前做好的海绵宝宝数据集
def load_dataset():
dataset = h5py.File('final_spangebob.h5', "r") # 加载训练数据
print(dataset.keys())
train_set_x_orig = np.array(dataset["train_set"][:]) # 从训练数据中提取出图片的特征数据
train_set_y_orig = np.array(dataset["train_set_tip"][:]) # 从训练数据中提取出图片的标签数据
test_set_x_orig = np.array(dataset["exam_set"][:])
test_set_y_orig = np.array(dataset["exam_set_tip"][:])
return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y = 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))
# 为了方便后面进行矩阵运算,我们需要将样本数据进行扁平化和转置
# -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
print ("train_set_x_flatten shape: " + str(train_set_x_flatten.shape))
print ("test_set_x_flatten shape: " + str(test_set_x_flatten.shape))
# 下面我们对特征数据进行了简单的标准化处理(除以255,使所有值都在[0,1]范围内)
# 为什么要对数据进行标准化处理呢?简单来说就是为了方便后面进行计算
train_set_x = train_set_x_flatten/255.
test_set_x = test_set_x_flatten/255.
工具函数
激活函数
用来把函数的值映射到0-1之间
'''激活函数sigmod'''
def sigmod(z):
s = 1/(1+np.exp(-z))
return s
初始化w,b
'''初始化权重数组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]
'''前向传播'''
A = sigmod(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):
# num_iterations - - 指定要优化多少次
# learning_rate - - 学习步进,是我们用来控制优化步进的参数
# print_cost - - 为True时,每优化100次就把成本cost打印出来, 以便我们观察成本的变化
costs = []
for i in range(num_iterations):
''' 用前向传播和反向传播来算dw,db'''
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 = sigmod(np.dot(w.T, X) + b)
for i in range(A.shape[1]):
if A[0,i] >= 0.5:
Y_prediction[0, i] = 1
return Y_prediction
最终的模型
'''最终的网络'''
def model01(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, costs = optimize(w, b, X_train, Y_train, num_iterations, learning_rate, print_cost)
'''从字典中分别取出训练好的w和b'''
w = parameters["w"]
b = parameters["b"]
'''使用训练好的w和b来分别对训练图片和测试图片进行预测'''
Y_prediction_train = predict(w, b, X_train)
Y_prediction_test = predict(w, b, X_test)
Y_prediction_train_rate = 100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100
Y_prediction_test_rate = 100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100
'''对训练数据和测试数据的预测准确度'''
print("训练数据; {}%".format(Y_prediction_train_rate))
print("测试数据; {}%".format(Y_prediction_test_rate))
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,
'Y_prediction_train_rate': Y_prediction_train_rate,
'Y_prediction_test_rate': Y_prediction_test_rate,
}
return d
计算过程
最终的模型目的是返回一个有训练过后的w和b数组的字典
这个w和b就是我们想要的模型
这里我设置分别在学习率为 range(0.001,0.11,0.001) 下优化4000次
all_Y_prediction_test_rate = []
all_Y_prediction_train_rate = []
all_costs = []
all_rates = []
for i in range(10, 0, -1):
print('hi')
d = model01(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 4000, learning_rate = 0.001*i, print_cost = True)
costs = np.squeeze(d['costs'])
all_rates.append(0.001*i)
all_costs.append(costs)
all_Y_prediction_train_rate.append(d['Y_prediction_train_rate'])
all_Y_prediction_test_rate.append(d['Y_prediction_test_rate'])
plt.plot(costs)
plt.ylabel('cost')
plt.xlabel('iterations(per hundreds)')
plt.title('learning rate: '+str(d['learning_rate']))
plt.show()
for i, item in enumerate(all_costs):
plt.plot(item, label=round(all_rates[i], 4))
plt.ylabel('cost')
plt.xlabel('iterations(per hundreds)')
legend = plt.legend(loc='upper center', shadow=True)
frame = legend.get_frame()
frame.set_facecolor('0.90')
# plt.axis([0, 40, 0, 4])
plt.show()
画出的图:
可以看到,从优化3000次后,成本越来越小了,也就是对训练集的掌握越来越好了
大约在学习率为0.003或0.004时是最好的
'''优化了4000次的不同学习率下对测试集的预测准确率'''
plt.plot(all_rates, all_Y_prediction_test_rate)
plt.ylabel('all_Y_prediction_test_rate')
plt.xlabel('learning_rate')
plt.title('all_Y_prediction_test_rate')
plt.show()
可以看到,选择0.003这样挺好的,对预测数据集的准确率达到了70%
所以,我们把0.003学习率下的w,b进行保存,作为最终的模型
d = model01(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 4000, learning_rate = 0.003, print_cost = True)
final = h5py.File('spangebob_w&b_best.h5', 'w')
final.create_dataset('w', data=d['w'])
final.create_dataset('b', data=d['b'])
final.close()
对未知图片预测
我上面所有的代码都写在 main_page.py 里
现在新开一个py文件
import skimage.transform as tf
import numpy as np
import matplotlib.pyplot as plt
import h5py
import main_page
temp_image = "C:\\Users\\11785\\Desktop\\1.jpg"
hf = h5py.File('spangebob_w&b_best.h5', 'r')
print(hf.keys())
w = hf['w']
b = hf['b']
print(np.array(w))
print(np.array(b))
print(str(w))
print(str(b))
image = np.array(plt.imread(temp_image))
my_image = tf.resize(image, (64, 64), mode='reflect').reshape((1, 64*64*3)).T
my_predicted_image = main_page.predict(np.array(w), np.array(b), my_image)
plt.imshow(image)
plt.show()
print("预测结果为 " + str(int(np.squeeze(my_predicted_image))))
<KeysViewHDF5 ['b', 'w']>
[[-0.00065091]
[-0.00054164]
[-0.00183722]
...
[-0.0015609 ]
[ 0.00187146]
[ 0.01345719]]
-0.23975435419281338
<HDF5 dataset "w": shape (12288, 1), type "<f8">
<HDF5 dataset "b": shape (), type "<f8">
预测结果为 0
0是没有海绵宝宝,1是有
(其实还是很弱的,选了几张图才得,毕竟只是单细胞生物,以后会有更强的)
就酱