歡迎你們前往騰訊雲+社區,獲取更多騰訊海量技術實踐乾貨哦~javascript
做者:鄭善友 騰訊MIG後臺開發工程師java
導語:在沒有CNN以及更先進的神經網絡的時代,樸素的想法是用多層感知機(MLP)作圖片分類的識別;但殘酷的現實是,MLP作這事的效果並不理想。本文經過使用MLP作圖片分類識別的嘗試做爲思路指引,實爲下一篇CNN相關筆記的引子文章。 本文的文檔和代碼,傳送門: github項目地址
做爲上篇筆記學習的延續,以及下一篇CNN的藥引,使用MLP來作圖片分類識別,實在是個不錯的過分例子。經過這個例子,從思路上引出一系列的問題,我不賣關子,自問自答吧,即:python
咱們有3個h5文件,存着不重複的圖片數據,分別是:git
拿train_catvnoncat.h5舉例,這個文件有2個索引:github
以我主子爲例子:算法
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個億。若是圖片更大呢?參數會成指數級膨脹,後果盡情想象。
仍是說明一下代碼流程吧:數組
代碼作的事情就是:微信
#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(準確度),準確度的計算公式是: 識別正確圖片數/圖片總數。
不算完全的解答:
MLP在作圖片分類識別的缺陷:
神經元是全鏈接的方式構成的神經網絡,全鏈接狀況下,假設圖片是1k*1k像素大小,那麼隱藏層個數和輸入層尺寸一致時,不考慮RGB顏色通道,單通道下,權重w參數個數會是:$(10^3∗10^3)^2=10^{12}$
=1千億(沒數錯0的話) 若是圖片再大點,參數膨脹到不可想象,直接致使的負面效果是:
上面已經列舉了要解決的幾個問題,這裏總結一下:
能解決以上問題的,衆所周知,就是CNN以及衆多更先進的神經網絡模型了。本文做爲一篇引子文章,也是CNN的導火索。 代碼在你手中,把第一層隱藏層設計成和輸入層同樣大,即 layers_dims = [12288, 12288, 20, 7, 5, 1]。還只是64*64的小圖片而已,那龜速,我和個人小破筆記本都不能忍啊。這也是爲何大神們發明CNN的緣由之一吧!
問答
TensorFlow:如何進行圖像識別?
相關閱讀
人臉識別技術發展及實用方案設計
圖像分析那些事︱AI來了
圖像識別基本算法之SURF
此文已由做者受權騰訊雲+社區發佈,原文連接:https://cloud.tencent.com/dev...
歡迎你們前往騰訊雲+社區或關注雲加社區微信公衆號(QcloudCommunity),第一時間獲取更多海量技術實踐乾貨哦~