机器学习分类器——案例(opencv sklearn svm ann)
機器學習分類器——案例(opencv sklearn svm ann python)
ps:最近師姐給我們留了一個任務,記錄一下從一開始的什么都不懂到現在把任務做出來,并從中學習到的東西吧。。。。
語言環境python3.7,用到的庫
任務要求:給定數據集train和test文件夾,其中文件夾中包含四個文件夾(后來才知道是對應于多分類的四個類別),數據格式是圖片(也是后來才知道已經灰度處理過了)
小插曲:本來想展示一下文件夾層及目錄,奈何圖片過多,效果并不好,記錄一下獲取文件結構圖的方法吧。
1.win+R cmd
2.進入想要展示的文件夾內
3.輸入tree/f>file.txt命令,在響應的文件夾下生成txt文件可以看到文件結構圖。
數據集目錄結構:
ps:一開始什么都不懂,后來讀文獻知道了處理問題的整體思路,先來說一下整體思路吧。
整體思路:
數據預處理
方法:我的理解是把圖片的像素變成0和255,來分割目標區域(細胞核),后面特征提取可以用到。
知識點:(方法原理可進一步了解)
直方圖均衡化( Histogram Equalization):一種增強圖像對比度的方法。
濾波: 盡量保留圖像細節特征的條件下對目標圖像的噪聲進行抑制 , 消除圖像中的噪聲成分叫作圖像的平滑化或濾波操作 。種類:均值濾波、中值濾波
圖像的閾值分割:基于區域的圖像分割技術,原理是把圖像像素點分為若干類。本次采用ostu法或者迭代法計算閾值(很多種方法)
程序代碼:
def ImgProcessing(img):imgHist = cv2.equalizeHist(img) # 直方圖均衡化,用于提高圖像的質量imgblur = cv2.blur(imgHist, (5, 5)) # 均值濾波imgthre, ostu = cv2.threshold(imgblur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # otsu法聚類計算閾值# print(imgthre)###最佳閾值imgthre=126(具體問題的值不一樣)return ostupath = "Resource\\train\\1_typical_epithelial_cell\\1_122.jpg" img = cv2.imread(path, 0)#把圖片讀進來 thres = ImgProcessing(imgcopy) cv2.namedWindow("result",0)cv2.resizeWindow("result",600,300)result = cv2.hconcat([thres,img])cv2.imshow('result',result)if cv2.waitKey(1) & 0xFF == ord('q'):break效果演示:如果想得到目標是黑色背景是白色,修改cv2.threshold的參數即可,因為后面的輪廓檢測要求傳入的目標是白色,故這里目標選擇白色。(也是采坑遇見錯誤查閱官方文檔才知道。。。)
去燥效果演示:
將預處理后的圖片保存到trainpro和testpro文件夾中
方法:傳入文件路徑,獲取每張圖片然后對每張圖片處理后保存到文件夾中
程序代碼:
def get_label_dir(path):for file_name in os.listdir(path):img_dir = os.path.join(path, file_name)# print(file_name)img = cv2.imread(img_dir,0)imgHist = cv2.equalizeHist(img) # 直方圖均衡化,用于提高圖像的質量imgblur = cv2.blur(imgHist, (5, 5)) # 均值濾波bestyuzhi1 = diedai(imgblur)#迭代法求閾值ret1, th1 = cv2.threshold(imgblur, bestyuzhi1, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)#file_name = '4'+file_name[1:]cv2.imwrite("Resource\\testpro\\6_garbage\\"+file_name,th1) get_label_dir("Resource\\test\\6_garbage")#每次只需要修改路徑即可獲取特征
本次計算11個基本特征值和Hog特征(還有很多特征可以自行查閱,具體問題具體分析)最后把特征保存到Features列表中,一個圖片對應一個11長度的列表。
基本特征:(輪廓特征)周長、面積、長度、寬度、圓度、橢圓度、矩形度、規劃形狀因子;(紋理特征)均值、方差、平滑度、熵值、三階矩;
Hog特征:一種在計算機視覺和圖像處理中用來進行物體檢測的特征描述子。它通過計算和統計圖像局部區域的梯度方向直方圖來構成特征。 通過提取有用信息并扔掉多余的信息來簡化圖像 。 特征描述子將一張大小為width×height×3 (通道數)的圖片化成一個長度為n的特征向量數組。以HOG特征為例,輸入圖像的大小是64×128×3,輸出是一個長度為3780(假設)的特征向量 。本次提取756個特征。
程序代碼:
def getContours(thres,Features):contours, hierarchy = cv2.findContours(thres, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)cnt = contours[0]# print(cv2. arcLength(contours,True)) #輪廓長度# print(cv2.contourArea(contours))#輪廓面積area = cv2.contourArea(contours[0])# print("輪廓的面積是:%f" % area)length = cv2.arcLength(contours[0],True)# print("輪廓的周長是:%f" % length)#圓度計算公式4*PI*Area/length^2a = area*4*math.pib = math.pow(length,2)if b!=0:roundness = a/belse:roundness = 0# print("輪廓圓度是:%f" % roundness)#最小外接矩形框rect = cv2.minAreaRect(contours[0])wideth = rect[1][0]highth = rect[1][1]box = cv2.cv2.Boxpoint() if imutils.is_cv2() else cv2.boxPoints(rect)box = np.int0(box)minrectarea = np.int0(rect[1][0]*rect[1][1])#計算矩形度rect_degree = area/minrectarea# print("輪廓矩形度是:%f" % rect_degree)# cv2.drawContours(imgcopy, [box], 0, (255, 0, 0), 1)# cv2.drawContours(imgcopy, contours, -1, (0, 0, 255), 1) # 畫出輪廓#計算橢圓度for i in range(len(contours)):if len(contours[i]) >= 5:cv2.drawContours(thres, contours, -1, (150, 10, 255), 3)ellipse = cv2.fitEllipse(contours[i])ellipse_area = np.int0(ellipse[1][0] * ellipse[1][1])ellipse_degree = 4 * area / ellipse_area# Features.append(round(ellipse_degree, 3))# print("輪廓橢圓度%d是:%f" % (i,ellipse_degree))d1 = ellipse[1][0]d2 = ellipse[1][1]if d1 * d2 * length !=0:REF = area * (3 * (d1 + d2) - 2 * math.sqrt(d1 * d2)) / (d1 * d2 * length)else :REF =0# cv2.imshow("Perfectlyfittedellipses", thres)# cv2.waitKey(0)# ellipse = cv2.fitEllipse(contours[0])# ellipse_area = np.int0(ellipse[1][0]*ellipse[1][1])# ellipse_degree = 4*area/ellipse_area# # cv2.ellipse(imgcopy,ellipse,(0,255,255),1)#可視化橢圓輪廓# #規劃形狀因子# print("規劃形狀因子是:%f" % REF)wenli_gt = cv2.moments(contours[0])# print("三階矩是:%f" % wenli_gt['mu02']) # 三階矩Features.append(round(wideth,3))Features.append(round(highth,3))Features.append(round(area,3))Features.append(round(length,3))Features.append(round(roundness,3))Features.append(round(rect_degree,3))Features.append(round(ellipse_degree,3))Features.append(round(REF,3))Features.append(round(wenli_gt['mu02'],3)) def grain_feature(img,Features):mean , stddv = cv2.meanStdDev(img)#圖像均值和標準差(方差)# print("均值為%f 方差為%f " % (mean[0][0],stddv[0][0]))wenli_r = 1-1/(1+stddv*stddv)# print("平滑度為%f" % wenli_r)imagea = np.histogram(img.ravel(), bins=256)[0]wenli_s = skimage.measure.shannon_entropy(imagea,base=2)# print("熵值是:%f" % wenli_s)Features.append(round(wenli_r[0][0],6))Features.append(round(wenli_s,3)) def get_features(path):Features_set = []for file_name in os.listdir(path):Features = []img_dir = os.path.join(path, file_name)# print(file_name)img = cv2.imread(img_dir,0)imgcopy = img.copy()thres = ImgProcessing(imgcopy)getContours(thres,Features) ###基本特征grain_feature(imgcopy,Features) #####紋理特征# Features = np.array(Features)# print(type(Features),type(Features_sets))Features_set.append(Features)return Features_set獲取Hog特征代碼:
def get_hog_feat(path):Features = []try:for file_name in os.listdir(path):img_dir = os.path.join(path, file_name)img = cv2.imread(img_dir,0)imgcopy = cv2.resize(img,(32,64))features, hog_img = ft.hog(imgcopy, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(2, 2), visualize=True)Features.append(features)except cv2.error:print(file_name)return Features制作數據集準備傳入模型中,將四類訓練集的特征都放入X_train中,Y_train存放標簽1,2,3,4(有的模型要求是0,1,2,3,代碼中有體現)
path_train = "Resource\\train" path_test = "Resource\\test" ###########制作訓練集 def get_data(path):X = []Y = []cnt =0for file_name in os.listdir(path):Features = []img_dir = os.path.join(path, file_name)Features = get_hog_feat(img_dir)cnt = cnt + 1for i in Features:X.append(i)Y.append(cnt)# cnt = cnt + 1 #XGB要求0123return X,Y X_train ,Y_train = get_data(path_train) X_test,Y_test = get_data(path_test)如果遇到傳入數據有空值的錯誤可以使用以下代碼
關于np.nan_to_num可查看官方文檔https://numpy.org/doc/stable/reference/generated/numpy.nan_to_num.html
X_train = np.nan_to_num(X_train) Y_train = np.nan_to_num(Y_train) X_test = np.nan_to_num(X_test) Y_test = np.nan_to_num(Y_test)數據降維
特征向量的維數過高會增加計算的復雜度,數據降維消除特征之間的數量級。
使用sklearn中的from sklearn.preprocessing import StandardScaler,使用方法可查看官方文檔,sklearn的文檔做的很好,有很多example,嘻嘻嘻。
sc_X = StandardScaler() X_trainscaled = sc_X.fit_transform(X_train) X_testscaled = sc_X.fit_transform(X_test) X_testscaled = np.nan_to_num(X_testscaled)ps:數據準備好開始訓練
分類器訓練和模型衡量標準
本次訓練包含svm支持向量機,ann人工神經網絡(MLP多層感知機),Decision Tree決策樹、XGBboost(種梯度提升決策樹的實現)k-nn(K近鄰),Naive Bayes(樸素貝葉斯),有很多方法可以使用,但是很多原理還需要進一步學習。。。
分類器的訓練模型參數均保存到.dat文件中,可以節約每次訓練的時間。
程序代碼:
###############SVM linear = svm.SVC(kernel='linear',C=1,decision_function_shape='ovo').fit(X_train ,Y_train) linear = svm.SVC(decision_function_shape='ovo').fit(X_train ,Y_train) linear_pred = linear.predict(X_test) linear = joblib.load("Hog_linear.dat") accuracy_lin = linear.score(X_test,Y_test) print("SVM-linear準確度為%.2f%%" % (accuracy_lin*100)) # joblib.dump(linear,"Hog_linear.dat")#保存模型 ##############ANN #MLP = MLPClassifier(solver='adam', alpha=1e-5,#256,128,64,32,hidden_layer_sizes=(30,30,30)random_state=100,activation='logistic').fit(X_trainscaled,Y_train) MLP = MLPClassifier().fit(X_trainscaled,Y_train) #joblib.dump(MLP,"Hog_MLP.dat")#保存模型 #MLP = joblib.load("Hog_MLP.dat")#加載模型 # MLP_pre = MLP.predict(X_testscaled) accuracy_ANN = MLP.score(X_testscaled,Y_test) print("Hog特征之ANN準確度%.2f%%" % (accuracy_ANN*100.0))About SVM:kernel(核函數linear、rbf、poly、sigmoid),gamma值、懲罰系數c的選取都會影響最終的準確度的,由于是多分類, 邏輯回歸和 SVM 等二元分類模型本身不支持多類分類,需要元策略 ,分類策略采用的是ovo,還有ovr。
關于分類策略ovo和ovr:
由于SVM本質上是二分類模型,多分類可以是二分類的延伸。例如給定多分類class 1,class 2,class 3,class4。
ovo(One-vs-One):
class1 vs class 2
class 1 vs class3 等總共有n(n-1)/2種(4*3/2=6)
ovr(One-vs-Rest)n種:
class 1 vs [class2,class3,class4]
class 2 vs [class1,class 3,class 4]
class 3 vs [class1,class 2 ,class4]
class4 vs [class1,class2,class3]
About ANN
ANN就是借鑒了神經突觸機制,在結點中設置了函數,比如sigmoid或者tanh函數,來完成抑制或激活的目標。
衡量標準
計算準確率(Accuracy)、精確率(Precision)、召回率(Recall)、F1-Measure的數值、畫AUC曲線和混淆矩陣。
準確率(Accuracy):1-錯誤率
精確率(Precision):有多少比例是好的
召回率(Recall):好的信息中有多少被檢索出來
F1-Measure的數值:對查準率/查全率的重視程度
混淆矩陣:看出有多少個分類正確,有多少個被分類到其他的類中
ROC-AUC曲線:ROC曲線下的面積
###########衡量標準 target_names = ['class 1', 'class 2', 'class 3','class 4'] print(classification_report(Y_test, MLP_pre, target_names=target_names)) ######混淆矩陣 disp = metrics.ConfusionMatrixDisplay.from_predictions(Y_test, MLP_pre) disp.figure_.suptitle("confusion matrix") print(f"confusion matrix:\n{disp.confusion_matrix}") plt.show() ######ROC曲線和AUC #model = RidgeClassifier() #model = SVC() model = MLPClassifier() roc_auc(MLP, X_train, Y_train, X_test=X_test, y_test=Y_test, encoder={1:'typical', 2:'Lymphocyte', 3:'Single',4:'garbage'})效果演示:
其他的分類器
#####################Decision Trees 決策樹DTC = tree.DecisionTreeClassifier() DTC.fit(X_trainscaled,Y_train) # joblib.dump(DTC,"Hog_DTC.dat") DTC = joblib.load("Hog_DTC.dat") accuracy_DTC = DTC.score(X_testscaled,Y_test) print("Hog特征之DTC準確度%.2f%%" % (accuracy_DTC*100.0)) # print(cross_val_score(DTC,X_train,Y_train,cv=10)) # tree.plot_tree(DT)#繪制樹 #可以pip graphviz導出樹到pdf ####################集成學習 ######XGBoost是一種梯度提升決策樹的實現 XGB = XGBClassifier().fit(X_trainscaled,Y_train) # XGB = joblib.load("Hog_XGB.dat") accuracy_XGB = XGB.score(X_testscaled,Y_test) print("Hog特征之XGB準確度%.2f%%" % (accuracy_XGB*100.0)) # joblib.dump(XGB,"Hog_XGB.dat")####################K-Nearest Neighbors K近鄰 n_neighbors = 20 h = 0.02 K_N = neighbors.KNeighborsClassifier(n_neighbors,weights="distance") K_N.fit(X_trainscaled,Y_train) # # K_N = joblib.load("Hog_KNN.dat") accuracy_KNN = K_N.score(X_testscaled, Y_test) print("Hog特征之KNN準確度%.2f%%" % (accuracy_KNN * 100.0)) # # joblib.dump(K_N,"Hog_KNN.dat") ##繪制accuracy和k取值的關系圖 acc = [] for i in range(1,40):neigh = neighbors.KNeighborsClassifier(n_neighbors = i).fit(X_trainscaled,Y_train)yhat = neigh.predict(X_testscaled)acc.append(metrics.accuracy_score(Y_test, yhat)) plt.figure(figsize=(10,6)) plt.plot(range(1,40),acc,color = 'blue',linestyle='dashed',marker='o',markerfacecolor='red', markersize=10) plt.title('accuracy vs. K Value') plt.xlabel('K') plt.ylabel('Accuracy') print("Maximum accuracy:-",max(acc),"at K =",acc.index(max(acc))) plt.show()############ Naive Bayes 樸素貝葉斯(種類多):多項式樸素貝葉斯(離散)高斯樸素貝葉斯(連續) NB_G = GaussianNB().fit(X_trainscaled,Y_train) NB_G = joblib.load("Hog_NB_G.dat") accuracy_NBG = NB_G.score(X_testscaled,Y_test) print("Hog特征之NB_G準確度%.2f%%" % (accuracy_NBG*100.0)) # joblib.dump(NB_G,"Hog_NB_G.dat")About DT
決策樹通過遞歸地進行特征選擇,將訓練集數據 D 進行分類最終生成一顆由節點和有向邊組成的樹結構。其中結點分為兩種類型:內部節點和葉節點,內部結點表示一個特征,葉結點表示一個類別。
About k-nn
即是給定一個訓練數據集,對新的輸入實例,在訓練數據集中找到與該實例最鄰近的K個實例,這K個實例的多數屬于某個類,就把該輸入實例分類到這個類中。(這就類似于現實生活中少數服從多數的思想)
ps:關于分類器的算法的原理和理解很淺,希望后期可以多看原理,多看背后的數學邏輯,對適合數據的參數選擇能力還不夠,加油吧。
總結
以上是生活随笔為你收集整理的机器学习分类器——案例(opencv sklearn svm ann)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android wifi讲解 wifi列
- 下一篇: 打蚊子表情包_打蚊子表情包 - 打蚊子微