前言
2013年的時候全肮,Kaggle發(fā)布了這樣的一個挑戰(zhàn)(https://www.kaggle.com/c/dogs-vs-cats):
In this competition, you'll write an algorithm to classify whether images contain either a dog or a cat. This is easy for humans, dogs, and cats. Your computer will find it a bit more difficult.
Dog or Cat?
這個挑戰(zhàn)提供了一個狗與貓的圖像標注過后的數(shù)據(jù)集,不限算法,實現(xiàn)對含有狗與貓的圖像進行分類订咸。在學(xué)習(xí)了這么久的神經(jīng)網(wǎng)絡(luò)之后,此時第一個在腦海中浮現(xiàn)出來的想法肯定是使用卷積神經(jīng)網(wǎng)絡(luò),畢竟卷積神經(jīng)網(wǎng)絡(luò)對對圖像分類的任務(wù)來說是具有極大的優(yōu)勢的。
那么在這一篇文章中艘包,我們將重點放在如何準備并處理這個數(shù)據(jù)集,以便Keras使用耀盗。
下載與處理數(shù)據(jù)集
Kaggle的Dogs and Cats的數(shù)據(jù)集可以從Microsoft的網(wǎng)站上進行下載想虎,下載地址如下:
https://www.microsoft.com/en-us/download/details.aspx?id=54765
數(shù)據(jù)集大小:787MB
每個分類的樣本有12,500個袍冷,這個樣本數(shù)量對于訓(xùn)練一個神經(jīng)網(wǎng)絡(luò)應(yīng)該是足夠的磷醋。
加載和處理數(shù)據(jù)集首先需要從系統(tǒng)讀取圖片,這就需要使用到我們的os模塊胡诗,os模塊主要用來遍歷目錄和結(jié)合路徑;同時處理圖像數(shù)據(jù)則需要使用OpenCV(圖像操作)和Numpy(數(shù)組操作)的包淌友;最后使用Pyplot來進行圖像的繪制煌恢。
import numpy as np
import os
import cv2
import matplotlib.pyplot as plt
由于OpenCV并非Anaconda集成的,因此需要單獨安裝震庭」宓郑可以通過pip install opencv-python
來安裝OpenCV或通過pip install opencv-contrib-python
來安裝帶額外功能的OpenCV版本。
在程序的最前面器联,我們需要指定數(shù)據(jù)集的路徑與包含的類別:
data_path = "D:/dev/pythonwork/dataset/kagglecatsanddogs_3367a/PetImages/"
categories = ["Dog", "Cat"]
由于不同的卷積網(wǎng)絡(luò)的輸入基本上是固定的二汛,而數(shù)據(jù)集中的圖像大小是不一樣的,因此我們需要統(tǒng)一所有圖片的大小拨拓。統(tǒng)一圖片的大小則需要用到Opencv的cv2.resize
函數(shù)肴颊。
首先,讓我們通過cv2.imread
來讀取所有的圖片渣磷,而后使用cv2.resize
修改圖片大小婿着。
# 定義圖像為50*50的大小
img_size = 50
train_data = []
def create_train_data():
for category in categories:
path = os.path.join(data_path, category)
class_num = categories.index(category)
for img in os.listdir(path):
try:
img_array = cv2.imread(os.path.join(path, img), cv2.IMREAD_GRAYSCALE)
new_array = cv2.resize(img_array, (img_size, img_size))
train_data.append([new_array, class_num])
except Exception as e:
pass
create_train_data()
上述代碼先是定義了一個空的列表作為我們的訓(xùn)練集。對于這個機器學(xué)習(xí)程序來說,我們的目的是讓其可以將狗與貓進行分類竟宋。因此提完,訓(xùn)練集應(yīng)該有特征與標簽,標簽就是用來區(qū)分狗與貓的標簽丘侠。由于我們前面定義的類別是一個字符串列表徒欣,因此這里需要將其轉(zhuǎn)換為0或1的數(shù)字。
而且便是讀取圖像與處理圖像蜗字。由于數(shù)據(jù)集中有一些圖像壞了帚称,從而會引起一些異常,所以這里采用try來將圖像處理的語句包裹起來秽澳,如若遇到異常則跳過闯睹。
最后,運行create_train_data()
函數(shù)之后担神,我們得到了一個包含特征與標簽的訓(xùn)練集楼吃。通過print(len(train_data))
來查看這個訓(xùn)練集發(fā)現(xiàn)其中一共有24946個樣本。
由于在讀取和處理圖像的時候妄讯,是先讀取Dog的圖像再讀取Cat的圖像孩锡,因此整個train_data的前12500個樣本會都是Dog,而后12500個樣本則都是Cat亥贸。這樣訓(xùn)練對機器學(xué)習(xí)程序來說會很不友好躬窜,因此,我們需要對其進行打亂(Shuffle)炕置。
import random
random.shuffle(train_data)
運行完shuffle方法之后荣挨,我們的訓(xùn)練集就被成功地打亂了。
最后朴摊,讓我們將準備好的訓(xùn)練集以特征與標簽的形式保存下來默垄。以機器學(xué)習(xí)程序的標準命名規(guī)則來以X來表示特征集,y來表示標簽甚纲。
for feature, label in train_data:
X.append(feature)
y.append(label)
X = np.array(X).reshape(-1, img_size, img_size, 1) # 最后的1代表grayscale 只有1個通道
準備完成之后口锭,將X和y通過pickle來保存下來,以便別的程序使用介杆。
import pickle
# pickle保存數(shù)據(jù)
pickle_out = open("X.pickle", "wb")
pickle.dump(X, pickle_out)
pickle_out.close()
pickle_out = open("y.pickle", "wb")
pickle.dump(y, pickle_out)
pickle_out.close()
# pickle讀取數(shù)據(jù)
pickle_in = open("X.pickle", "rb")
X = pickle.load(pickle_in)
保存完成之后鹃操,我們將會在相應(yīng)的文件夾下面找到X.pickle與y.pickle文件。
在下一節(jié)中春哨,我們通過Keras的Sequential模型來建立并訓(xùn)練一個卷積神經(jīng)網(wǎng)絡(luò)荆隘。