欢迎你们前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~javascript
做者:郑善友 腾讯MIG后台开发工程师java
导语:在没有CNN以及更先进的神经网络的时代,朴素的想法是用多层感知机(MLP)作图片分类的识别;但残酷的现实是,MLP作这事的效果并不理想。本文经过使用MLP作图片分类识别的尝试做为思路指引,实为下一篇CNN相关笔记的引子文章。 本文的文档和代码,传送门: github项目地址python
def save_imgs_to_h5file(h5_fname, x_label, y_label, img_paths_list, img_label_list):
# 构造n张图片的随机矩阵
data_imgs = np.random.rand(len(img_paths_list), 64, 64, 3).astype('int')
label_imgs = np.random.rand(len(img_paths_list), 1).astype('int')
# plt.imread能够把图片以多维数组形式读出来,而后咱们存成 n*n*3 的矩阵
for i in range(len(img_paths_list)):
data_imgs[i] = np.array(plt.imread(img_paths_list[i]))
label_imgs[i] = np.array(img_label_list[i])
# 建立h5文件,按照指定的索引label存到文件中,完事了
f = h5py.File(h5_fname, 'w')
f.create_dataset(x_label, data=data_imgs)
f.create_dataset(y_label, data=label_imgs)
f.close() return data_imgs, label_imgs
#用法
# 图片label为1表明这是一张喵星人的图片,0表明不是
save_imgs_to_h5file('datasets/my_cat_misu.h5', 'mycat_set_x', 'mycat_set_y', ['misu.jpg'],[1])
复制代码
【插播】:有人会想,第一层隐藏层的神经元和输入层数量一致是否是会好点?理论上会好点,可是这涉及到MLP的一个缺陷,由于全链接状况下,这样作,第一层的权重w参数就有1228的平方个,约为1.5个亿。若是图片更大呢?参数会成指数级膨胀,后果尽情想象。git
仍是说明一下代码流程吧:github
#coding:utf-8
import h5py
import matplotlib.font_manager as fm
import matplotlib.pyplot as plt
import numpy as np
from NeuralNetwork import *
font = fm.FontProperties(fname='/System/Library/Fonts/STHeiti Light.ttc')
def load_Cat_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"][:])
mycat_dataset = h5py.File('datasets/my_cat_misu.h5', "r")
mycat_set_x_orig = np.array(mycat_dataset["mycat_set_x"][:])
mycat_set_y_orig = np.array(mycat_dataset["mycat_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]))
mycat_set_y_orig = mycat_set_y_orig.reshape((1, mycat_set_y_orig.shape[0]))
return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, mycat_set_x_orig, mycat_set_y_orig,classes
def predict_by_modle(x, y, nn):
m = x.shape[1]
p = np.zeros((1,m))
output, caches = nn.forward_propagation(x)
for i in range(0, output.shape[1]):
if output[0,i] > 0.5:
p[0,i] = 1
else:
p[0,i] = 0
# 预测出来的结果和指望的结果比对,看看准确率多少:
# 好比100张预测图片里有50张猫的图片,只识别出40张,那么识别率就是80%
print(u"识别率: " + str(np.sum((p == y)/float(m))))
return np.array(p[0], dtype=np.int), (p==y)[0], np.sum((p == y)/float(m))*100
def save_imgs_to_h5file(h5_fname, x_label, y_label, img_paths_list, img_label_list):
data_imgs = np.random.rand(len(img_paths_list), 64, 64, 3).astype('int')
label_imgs = np.random.rand(len(img_paths_list), 1).astype('int')
for i in range(len(img_paths_list)):
data_imgs[i] = np.array(plt.imread(img_paths_list[i]))
label_imgs[i] = np.array(img_label_list[i])
f = h5py.File(h5_fname, 'w')
f.create_dataset(x_label, data=data_imgs)
f.create_dataset(y_label, data=label_imgs)
f.close()
return data_imgs, label_imgs
if __name__ == "__main__":
# 图片label为1表明这是一张喵星人的图片,0表明不是
#save_imgs_to_h5file('datasets/my_cat_misu.h5', 'mycat_set_x', 'mycat_set_y', ['misu.jpg'],[1])
train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, mycat_set_x_orig, mycat_set_y_orig, classes = load_Cat_dataset()
train_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1).T
test_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1).T
mycat_x_flatten = mycat_set_x_orig.reshape(mycat_set_x_orig.shape[0], -1).T
train_set_x = train_x_flatten / 255.
test_set_x = test_x_flatten / 255.
mycat_set_x = mycat_x_flatten / 255.
print(u"训练图片数量: %d" % len(train_set_x_orig))
print(u"测试图片数量: %d" % len(test_set_x_orig))
plt.figure(figsize=(10, 20))
plt.subplots_adjust(wspace=0,hspace=0.15)
for i in range(len(train_set_x_orig)):
plt.subplot(21,10, i+1)
plt.imshow(train_set_x_orig[i],interpolation='none',cmap='Reds_r',vmin=0.6,vmax=.9)
plt.xticks([])
plt.yticks([])
plt.savefig("cat_pics_train.png")
plt.show()
plt.figure(figsize=(8, 8))
plt.subplots_adjust(wspace=0, hspace=0.1)
for i in range(len(test_set_x_orig)):
ax = plt.subplot(8, 8, i + 1)
im = ax.imshow(test_set_x_orig[i], interpolation='none', cmap='Reds_r', vmin=0.6, vmax=.9)
plt.xticks([])
plt.yticks([])
plt.savefig("cat_pics_test.png")
plt.show()
plt.figure(figsize=(2, 2))
plt.subplots_adjust(wspace=0, hspace=0)
for i in range(len(mycat_set_x_orig)):
ax = plt.subplot(1, 1, i + 1)
im = ax.imshow(mycat_set_x_orig[i], interpolation='none', cmap='Reds_r', vmin=0.6, vmax=.9)
plt.xticks([])
plt.yticks([])
plt.savefig("cat_pics_my.png")
plt.show()
# 用训练图片集训练模型
layers_dims = [12288, 20, 7, 5, 1]
nn = NeuralNetwork(layers_dims, True)
nn.set_xy(train_set_x, train_set_y_orig)
nn.set_num_iterations(10000)
nn.set_learning_rate(0.0075)
nn.training_modle()
# 结果展现说明:
# 【识别正确】:
# 1.原图是猫,识别为猫 --> 原图显示
# 2.原图不是猫,识别为不是猫 --> 下降显示亮度
# 【识别错误】:
# 1.原图是猫,可是识别为不是猫 --> 标红显示
# 2.原图不是猫, 可是识别成猫 --> 标红显示
# 训练用的图片走一遍模型,观察其识别率
plt.figure(figsize=(10, 20))
plt.subplots_adjust(wspace=0, hspace=0.15)
pred_train, true, accuracy = predict_by_modle(train_set_x, train_set_y_orig, nn)
for i in range(len(train_set_x_orig)):
ax = plt.subplot(21, 10, i + 1)
x_data = train_set_x_orig[i]
if pred_train[i] == 0 and train_set_y_orig[0][i] == 0:
x_data = x_data/5
if true[i] == False:
x_data[:, :, 0] = x_data[:, :, 0] + (255 - x_data[:, :, 0])
im = plt.imshow(x_data,interpolation='none',cmap='Reds_r',vmin=0.6,vmax=.9)
plt.xticks([])
plt.yticks([])
plt.suptitle(u"Num Of Pictrues: %d\n Accuracy: %.2f%%" % (len(train_set_x_orig), accuracy), y=0.92, fontsize=20)
plt.savefig("cat_pics_train_predict.png")
plt.show()
# 不属于训练图片集合的测试图片,走一遍模型,观察其识别率
plt.figure(figsize=(8, 8))
plt.subplots_adjust(wspace=0, hspace=0.1)
pred_test, true, accuracy = predict_by_modle(test_set_x, test_set_y_orig, nn)
for i in range(len(test_set_x_orig)):
ax = plt.subplot(8, 8, i + 1)
x_data = test_set_x_orig[i]
if pred_test[i] == 0 and test_set_y_orig[0][i] == 0:
x_data = x_data/5
if true[i] == False:
x_data[:, :, 0] = x_data[:, :, 0] + (255 - x_data[:, :, 0])
im = ax.imshow(x_data, interpolation='none', cmap='Reds_r', vmin=0.6, vmax=.9)
plt.xticks([])
plt.yticks([])
plt.suptitle(u"Num Of Pictrues: %d\n Accuracy: %.2f%%" % (len(mycat_set_x_orig), accuracy), fontsize=20)
plt.savefig("cat_pics_test_predict.png")
plt.show()
# 用我家主子的照骗,走一遍模型,观察其识别率,由于只有一张图片,因此识别率要么 100% 要么 0%
plt.figure(figsize=(2, 2.6))
plt.subplots_adjust(wspace=0, hspace=0.1)
pred_mycat, true, accuracy = predict_by_modle(mycat_set_x, mycat_set_y_orig, nn)
for i in range(len(mycat_set_x_orig)):
ax = plt.subplot(1, 1, i+1)
x_data = mycat_set_x_orig[i]
if pred_mycat[i] == 0 and mycat_set_y_orig[0][i] == 0:
x_data = x_data/5
if true[i] == False:
x_data[:, :, 0] = x_data[:, :, 0] + (255 - x_data[:, :, 0])
im = ax.imshow(x_data, interpolation='none', cmap='Reds_r', vmin=0.6, vmax=.9)
plt.xticks([])
plt.yticks([])
if pred_mycat[i] == 1:
plt.suptitle(u"我:'我主子是喵星人吗?'\nA I :'是滴'", fontproperties = font)
else:
plt.suptitle(u"我:'我主子是喵星人吗?'\nA I :'唔系~唔系~'", fontproperties = font)
plt.savefig("cat_pics_my_predict.png")
plt.show()
复制代码
结果展现说明:算法
【识别正确】:数组
【识别错误】:微信
图片标题会显示Accuracy(准确度),准确度的计算公式是: 识别正确图片数/图片总数。网络
$(10^3∗10^3)^2=10^{12}$
=1千亿(没数错0的话) 若是图片再大点,参数膨胀到不可想象,直接致使的负面效果是:
上面已经列举了要解决的几个问题,这里总结一下:数据结构
能解决以上问题的,众所周知,就是CNN以及众多更先进的神经网络模型了。本文做为一篇引子文章,也是CNN的导火索。 代码在你手中,把第一层隐藏层设计成和输入层同样大,即 layers_dims = [12288, 12288, 20, 7, 5, 1]。还只是64*64的小图片而已,那龟速,我和个人小破笔记本都不能忍啊。这也是为何大神们发明CNN的缘由之一吧!
问答
相关阅读
此文已由做者受权腾讯云+社区发布,原文连接:https://cloud.tencent.com/developer/article/1150162?fromSource=waitui
欢迎你们前往腾讯云+社区或关注云加社区微信公众号(QcloudCommunity),第一时间获取更多海量技术实践干货哦~