我是用 jupyter notebook寫的,各個功能模塊清楚分明,順便推薦給大家。 以圖片分類為例:
主要依賴于:
- scikit-learn
- scikit-image
- matplotlib
- jupyter notebook
- numpy
- cv2 (傾向于使用 skimage image 代替之, skimage 使用的是 圖像坐標 (通過行列檢索),cv2使用笛卡爾坐標檢索(x,y))
直接開始正文:
導入依賴庫
- 寫個 lib.ipynb 將依賴庫都放進去
%matplotlib inline
import platform
SYS = platform.system()
if 'Linux' in SYS:
%run /home/v/WORKSPACE/GIT/LIB/lib.ipynb
else:
%run d:/WORKSPACE/git/LIB/lib.ipynb
t1 = toc()
注意事項:
- lib.ipynb 是依賴庫函數所在文件
- 為了方便linux 和 win 都能運行,所以加入最后幾行。
- toc()函數是自己寫的函數,為了方便整體計時,存放在lib里面,局部計時有%%timeit命令。
數據庫(圖片)路徑
trainset = ps('image path for training ')
testset = ps('image path for testing')
print ("[INFO] There are %d classes in the trainset" % len(os.listdir(trainset)))
注意事項:
- ps函數可有可無,有興趣的朋友可以留言。
- 每個文件夾存放一個類別的圖片,文件夾的命名要體現圖片label和category name,這樣做會在分類上省事一些,通過下面的特征提取代碼,大家可以看到。我的數據庫是這樣命名的:
train and test folders
class folders in train set
這樣命名的好處很快可以在特征提取模塊看到。
特征提取 -- HOG 特征
%%time
x_train=[]
y_train=[]
for floder_nmae in tqdm(os.listdir(trainset)):
label= int( floder_nmae.split("__")[0] )
class_path=os.path.join(trainset,floder_nmae)
for img_name in os.listdir(class_path):
img_path=os.path.join(class_path,img_name)
## readin the original image
ROI = imread(img_path, as_grey=True, resize =True, width =200, height =100)
x_train.append(HOG(ROI,ori=9, ppc=(20, 20), cpb=(2, 2)))
y_train.append(label)
x_test=[]
y_test=[]
for class_folder in tqdm(os.listdir(testset)):
label= int( class_folder.split("__")[0] )
class_path=os.path.join(testset,class_folder)
for j in os.listdir(class_path):
img_path=os.path.join(class_path,j)
## readin the original image
ROI = imread(img_path, as_grey=True, resize =True, width =200, height =100)
x_test.append(HOG(ROI,ori=9,ppc=(20, 20), cpb=(2, 2)))
y_test.append(label)
print (" number of train samples : %d " % len(x_train) )
print (" number of test samples : %d " % len(x_test) )
print (" feature dim is : %d " % len(x_train[0]) )
注意事項:
- 文件夾命名的好處現在知道了吧,直接 .split("__")就可以得到類別label
- imread 函數和HOG函數都被我簡單封裝了下,存在lib里面,原因是不同語言各種各樣的 圖片讀取, resize, 灰度化函數搞得我好亂啊,所以索性同一放在imread函數里面,集 圖片讀取,灰度化, resize, rescale于一身。如有朋友需要的話,我可以公布下這個函數。HOG函數也是一樣,skimage不僅在HOG函數bins的方向上弄得不好,而且函數明明也過于冗長和復雜. ori = orientation, ppc = pixel per cell, cpb = cell per block 沒人會質疑我的簡化吧。
- 這部分的輸出是這樣的:
module output
wall time 就是jupyter notebook magic函數的功能,給出當前cell的運行時間。有機會寫一系列 jupyter notebook (ipython) magic function的簡文(如果有人提出的話)。
分類器的訓練(linear SVM)
直接上代碼
%%time
clf = svm.LinearSVC()
parameters = {
'C': np.arange(1, 15, 1),
'multi_class': ['crammer_singer']
}
# run randomized search
n_iter_search = 10
clf = RandomizedSearchCV(clf,
param_distributions = parameters,
n_iter = n_iter_search,
n_jobs = 4,
pre_dispatch = '2*n_jobs')
clf.fit(x_train, y_train)
- crammer singer SVM 是為多類別分類設計的,這個我喜歡,因為效果好。
- 現在知道 特征列表和label 列表明明的好處了吧。 x, y, train。體會一下。
- 我特意加入了參數選擇這一塊,調參是個大問題,如果機器允許,就讓他自己去找吧,當然是通過 coss validation的方式, Randomized SearchCV 默認是將訓練數據5-fold還是6-fold, 這個參數也可以修改,需要的話可以百度 scikit learn documentation.
- 這部分的輸出: 有需要解釋的地方可以提問。。。。。。
module output
測試 --測試集
這部分沒啥說的, scikit learn 搞的函數接口還是簡單易懂的。
y_pred = clf.predict(x_test)
分類結果 accuracy
- 這里只提供了我寫的 acc函數,scikit learn 沒有提供acc的檢測接口。 當然還有其他的準則去檢驗,如:precision, recall, f1 score. 這些還是不如acc 表達的清楚:分對的個數除以要分類的樣本個數。
- 依舊,acc被我封裝起來了,存在lib.ipynb里面。
- 上結果:
Paste_Image.png
- 不用多解釋了吧。
- 函數總體運行時間,通過elapsed_time 得到, 現在知道toc()的作用了吧。