from sklearn import svm
1. 數據預處理
針對《Python數據分析與挖掘實戰》一書中第9章“基於水色圖像的水質評價”。需要對原始的203張圖片進行預處理,得到專家樣本集。然后再使用svm分類器進行訓練測試。
1 #!/usr/bin/env python 2 #-*- coding:utf-8 -*- 3 #數據預處理 4 5 from PIL import Image 6 import matplotlib.pyplot as plt 7 import os 8 import numpy as np 9 import pandas as pd 10 11 inputfile='../data/images' 12 outputfile='../data/result.xls' 13 14 #注意此處:得到一個包含圖片名(如:'1_10.jpg')的列表 15 imgslist=os.listdir(inputfile) 16 17 result=[] 18 for i in range(len(imgslist)): #203張待處理圖片 19 #label,number=imgslist[i].rstrip('.jpg').split('_') #label,number分別表示類別和序號 20 la=imgslist[i].rstrip('.jpg').split('_') 21 #將列表中數字字符串轉換為數值 22 la_numbers=[int(x) for x in la] 23 24 '''1.圖片切割''' 25 img=Image.open(inputfile+'/'+imgslist[i]) 26 M,N=img.size 27 box=[N/2-50,M/2-50,N/2+50,M/2+50] 28 roi=img.crop(box) 29 '''切割完成(100×100)''' 30 31 '''2.特征提取''' 32 #R,G,B=roi.split() #分離三個顏色通道 33 roi3=np.array(roi)/[256.0,256.0,256.0] 34 E=1.0/10000*(roi3.sum(axis=0).sum(axis=0)) #一階顏色矩;有100×100個像素 35 err=roi3-E 36 delta=np.sqrt(1.0/10000*(err**2).sum(axis=0).sum(axis=0)) #二階顏色矩 37 #s=pow(1.0/N*(pow(roi3-E,3).sum(axis=0).sum(axis=0)),1.0/3) 38 a=1.0/10000*(pow(err,3).sum(axis=0).sum(axis=0)) 39 s=abs(a)**(1.0/3)*-1 #三階顏色矩;注意:負數開立方方法 40 ''' 41 r_E,g_E,b_E=E 42 r_del,g_del,b_del=delta 43 r_s,g_s,b_s=s 44 ''' 45 re=np.concatenate((la_numbers,E,delta,s)) #數組水平拼接,concatenate((a,b),axis=0) 46 result.append(re) 47 '''特征提取完畢''' 48 49 cols=[u'水質類別',u'序號',u'R通道一階矩',u'G通道一階矩',u'B通道一階矩',\ 50 u'R通道二階矩',u'G通道二階矩',u'B通道二階矩',\ 51 u'R通道三階矩',u'G通道三階矩',u'B通道三階矩',] 52 res=pd.DataFrame(result,columns=cols) 53 res.to_excel(outputfile,index=False) #index=False
2. svm
1 #!/usr/bin/env python 2 #-*- coding:utf-8 -*- 3 4 import pandas as pd 5 import numpy as np 6 7 inputfile='../data/moment.csv' 8 data=pd.read_csv(inputfile,encoding='gbk') #讀取數據,指定編碼為gbk 9 data=data.as_matrix() 10 11 ''' 12 出現問題:采用random.shuffle(data)導致data發生不可預知的變化 13 解決辦法:采用numpy.random.shuffle(data)沒有問題 14 ''' 15 #from random import shuffle #引入隨機函數 16 np.random.shuffle(data) 17 data_train=data[:int(0.8*len(data)),:] #選取80%為訓練數據 18 data_test=data[int(0.8*len(data)):,:] #選取20%為測試數據 19 20 x_train=data_train[:,2:]*30 #放大特征 21 y_train=data_train[:,0].astype(int) 22 x_test=data_test[:,2:]*30 #放大特征 23 y_test=data_test[:,0].astype(int) 24 25 '''導入模型相關的函數,建立並且訓練模型''' 26 from sklearn import svm 27 model=svm.SVC() 28 model.fit(x_train,y_train) 29 30 '''保存/加載模型''' 31 import pickle 32 pickle.dump(model,open('../tmp/svm.model','wb')) 33 #model=pickle.load(open('../tmp/svm.model','rb')) 34 35 '''導入輸出相關的庫,生成混淆矩陣''' 36 from sklearn import metrics 37 cm_train=metrics.confusion_matrix(y_train,model.predict(x_train)) #訓練數據的混淆矩陣 38 cm_test=metrics.confusion_matrix(y_test,model.predict(x_test)) #測試數據的混淆矩陣 39 40 '''保存結果''' 41 outputfile1='../tmp/cm_train.xls' 42 outputfile2='../tmp/cm_test.xls' 43 pd.DataFrame(cm_train,index=range(1,6),columns=range(1,6)).to_excel(outputfile1) 44 pd.DataFrame(cm_test,index=range(1,6),columns=range(1,6)).to_excel(outputfile2)
部分原始數據展示:
得到結果:
cm_train:
cm_test:
遇到問題:
11 '''
12 出現問題:采用random.shuffle(data)導致data發生不可預知的變化(破壞了原數據)
13 解決辦法:采用numpy.random.shuffle(data)沒有問題
14 '''