1. 程式人生 > >機器學習之貝葉斯演算法影象分類

機器學習之貝葉斯演算法影象分類

在這裡插入圖片描述
資料集:資料集採用Sort_1000pics資料集。資料集包含1000張圖片,總共分為10類。分別是人(0),沙灘(1),建築(2),大卡車(3),恐龍(4),大象(5),花朵(6),馬(7),山峰(8),食品(9)十類,每類100張,(資料集可以到網上下載)。
在這裡插入圖片描述
ubuntu16.04虛擬作業系統,在分配記憶體4G,處理器為1個CPU下的環境下執行。
將所得到的圖片至“./photo目錄下”,(這裡採用的是Anaconda3作為開發環境)。可以參考上一篇
伯努利分佈理論基礎:
該分佈研究的是一種特殊的實驗,這種實驗只有兩個結果要麼成功要麼失敗,且每次實驗是獨立的並每次實驗都有固定的成功概率p。用伯努利樸素貝葉斯實現對影象的分類,首先伯努利分類物件是0,1分類,故此需要將影象畫素進行閾值0,1劃分。
在這裡插入圖片描述

import datetime
starttime = datetime.datetime.now()

import numpy as np
from sklearn.cross_validation import train_test_split
from sklearn.metrics import confusion_matrix, classification_report
import os
import cv2

X = []
Y = []

for i in range(0, 10):
    #遍歷資料夾,讀取圖片
    for f in os.listdir("./photo/%s" % i):
        #開啟一張圖片並灰度化
        Images = cv2.imread("./photo/%s/%s" % (i, f)) 
        image=cv2.resize(Images,(256,256),interpolation=cv2.INTER_CUBIC)
        hist = cv2.calcHist([image], [0,1], None, [256,256], [0.0,255.0,0.0,255.0]) 
        X.append(((hist/255).flatten()))
        Y.append(i)
X = np.array(X)
Y = np.array(Y)
#切分訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.3, random_state=1)
#隨機率為100%(保證唯一性可以對比)選取其中的30%作為測試集

from sklearn.preprocessing import binarize 
from sklearn.preprocessing import LabelBinarizer

class ML:
    def predict(self, x):
        #預測標籤
        X = binarize(x, threshold=self.threshold)
        #使對數似然函式最大的值也使似然函式最大
        #Y_predict = np.dot(X, np.log(prob).T)+np.dot(np.ones((1,prob.shape[1]))-X, np.log(1-prob).T)
        #等價於  lnf(x)=xlnp+(1-x)ln(1-p)
        Y_predict = np.dot(X, np.log(self.prob).T)-np.dot(X, np.log(1-self.prob).T) + np.log(1-self.prob).sum(axis=1)
        
        return self.classes[np.argmax(Y_predict, axis=1)]
        
class Bayes(ML): 
    def __init__(self,threshold):
        self.threshold = threshold
        self.classes = []
        self.prob = 0.0
        
    def fit(self, X, y):
        
        #標籤二值化
        labelbin = LabelBinarizer()
        Y = labelbin.fit_transform(y) 
        self.classes = labelbin.classes_ #統計總的類別,10類
        Y = Y.astype(np.float64)
        
        #轉換成二分類問題
        X = binarize(X, threshold=self.threshold)#特徵二值化,threshold閾值根據自己的需要適當修改
        feature_count = np.dot(Y.T, X) #矩陣轉置,對相同特徵進行融合
        class_count = Y.sum(axis=0) #統計每一類別出現的個數
        
        #拉普拉斯平滑處理,解決零概率的問題
        alpha = 1.0
        smoothed_fc = feature_count + alpha
        smoothed_cc = class_count + alpha * 2
        self.prob = smoothed_fc/smoothed_cc.reshape(-1, 1)
        
        return self
        
clf0 = Bayes(0.2).fit(X_train,y_train) #0.2表示閾值
predictions_labels = clf0.predict(X_test)
print(confusion_matrix(y_test, predictions_labels))
print (classification_report(y_test, predictions_labels))
endtime = datetime.datetime.now()
print (endtime - starttime)

實驗結果為:

[[20  0  0  0  0  1  0 10  0  0]
 [ 1  2  5  0  0  0  0 23  0  0]
 [ 3  0  9  0  1  0  0 13  0  0]
 [ 0  0  1 18  0  1  1  5  0  3]
 [ 0  0  0  0 30  1  0  0  0  1]
 [ 0  0  0  0  1  6  0 26  0  1]
 [ 3  0  0  2  0  0 21  3  0  1]
 [ 0  0  0  0  0  0  0 26  0  0]
 [ 2  0  0  2  1  1  0 21  2  2]
 [ 2  0  2  3  1  0  1 15  0  6]]
             precision    recall  f1-score   support

          0       0.65      0.65      0.65        31
          1       1.00      0.06      0.12        31
          2       0.53      0.35      0.42        26
          3       0.72      0.62      0.67        29
          4       0.88      0.94      0.91        32
          5       0.60      0.18      0.27        34
          6       0.91      0.70      0.79        30
          7       0.18      1.00      0.31        26
          8       1.00      0.06      0.12        31
          9       0.43      0.20      0.27        30

avg / total       0.70      0.47      0.45       300

0:00:05.261369

大家可根據自己的資料集影象,調整劃分閾值,可以得到不同的分類精度。程式碼參考了from sklearn.naive_bayes import BernoulliNB裡面的程式碼。下面貼出整合的程式碼:

import datetime
starttime = datetime.datetime.now()

import numpy as np
from sklearn.cross_validation import train_test_split
from sklearn.metrics import confusion_matrix, classification_report
import os
import cv2

X = []
Y = []

for i in range(0, 10):
    #遍歷資料夾,讀取圖片
    for f in os.listdir("./photo/%s" % i):
        #開啟一張圖片並灰度化
        Images = cv2.imread("./photo/%s/%s" % (i, f)) 
        image=cv2.resize(Images,(256,256),interpolation=cv2.INTER_CUBIC)
        hist = cv2.calcHist([image], [0,1], None, [256,256], [0.0,255.0,0.0,255.0]) 
        X.append(((hist/255).flatten()))
        Y.append(i)
X = np.array(X)
Y = np.array(Y)
#切分訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.3, random_state=1)

from sklearn.naive_bayes import BernoulliNB
clf0 = BernoulliNB().fit(X_train, y_train)
predictions0 = clf0.predict(X_test)
print (classification_report(y_test, predictions0))
endtime = datetime.datetime.now()
print (endtime - starttime)
precision    recall  f1-score   support

          0       0.52      0.42      0.46        31
          1       0.48      0.52      0.50        31
          2       0.39      0.54      0.45        26
          3       0.63      0.59      0.61        29
          4       0.76      0.88      0.81        32
          5       0.58      0.41      0.48        34
          6       0.94      0.53      0.68        30
          7       0.51      0.69      0.59        26
          8       0.47      0.52      0.49        31
          9       0.75      0.80      0.77        30

avg / total       0.61      0.59      0.59       300

0:00:05.426743