欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python OpenCV實戰(zhàn)之與機器學(xué)習(xí)的碰撞

 更新時間:2021年12月03日 11:55:51   作者:盼小輝丶  
機器學(xué)習(xí)是人工智能的子集,為計算機以及其它具有計算能力的系統(tǒng)提供自動預(yù)測或決策的能力。本文主要介紹了OpenCV 提供的常見機器學(xué)習(xí)算法和技術(shù),用于解決計算機視覺項目中的實際問題,需要的朋友可以參考一下

0. 前言

機器學(xué)習(xí)是人工智能的子集,它為計算機以及其它具有計算能力的系統(tǒng)提供自動預(yù)測或決策的能力,諸如虛擬助理、車牌識別系統(tǒng)、智能推薦系統(tǒng)等機器學(xué)習(xí)應(yīng)用程序給我們的日常生活帶來了便捷的體驗。機器學(xué)習(xí)的蓬勃發(fā)展,得益于以下三個關(guān)鍵因素:1) 海量數(shù)據(jù)集;2) 算法的快速發(fā)展;3) 計算機硬件的發(fā)展。在本文中,我們將學(xué)習(xí) OpenCV 提供的常見機器學(xué)習(xí)算法和技術(shù),用于解決計算機視覺項目中的實際問題,例如分類和回歸問題。

1. 機器學(xué)習(xí)簡介

機器學(xué)習(xí)是利用計算機編程,從歷史數(shù)據(jù)中學(xué)習(xí)以對新數(shù)據(jù)進行預(yù)測的過程。機器學(xué)習(xí)可以分為三類——監(jiān)督學(xué)習(xí)、無監(jiān)督學(xué)習(xí)和半監(jiān)督學(xué)習(xí),這些技術(shù)所包含的算法如下圖所示:

1.1 監(jiān)督學(xué)習(xí)

監(jiān)督學(xué)習(xí)使用的樣本都有相應(yīng)的期望輸出值(或稱為樣本標(biāo)簽),由于我們知道每個訓(xùn)練數(shù)據(jù)的正確標(biāo)簽,因此監(jiān)督學(xué)習(xí)可以根據(jù)預(yù)測與相應(yīng)的期望輸出之間的差異來校正這些預(yù)測?;谶@些校準(zhǔn),算法可以從錯誤中學(xué)習(xí)以調(diào)整其內(nèi)部參數(shù),以擬合出最接近樣本集合與相應(yīng)的期望輸出之間的函數(shù)。

監(jiān)督學(xué)習(xí)問題可以進一步分為以下分類和回歸:

  1. 分類:當(dāng)輸出變量是類別時,可以認為該問題是分類問題。在分類問題中,算法將輸入映射到輸出標(biāo)簽。
  2. 回歸:當(dāng)輸出變量為實數(shù)時,在回歸問題中,算法將輸入映射到連續(xù)的實數(shù)輸出。

在監(jiān)督學(xué)習(xí)中,主要需要考慮以下問題:

偏差-方差的權(quán)衡 (Bias-variance trade-off):模型對數(shù)據(jù)欠擬合的模型具有高偏差,而對數(shù)據(jù)過擬合的模型具有高方差:

偏差是由于學(xué)習(xí)算法中的錯誤假設(shè)而產(chǎn)生的誤差,可以定義為模型的預(yù)測與期望的正確值之間的差異。具有高偏差的模型無法找到數(shù)據(jù)中的所有模式(欠擬合),因此它不能很好地擬合訓(xùn)練集,也不會很好地擬合測試集。

方差定義為算法學(xué)習(xí)錯誤事物的傾向,其會同時擬合數(shù)據(jù)中的真實信號以及噪聲。因此,具有高方差的模型(過擬合)非常適合訓(xùn)練集,但無法泛化到測試集,因為它學(xué)習(xí)了數(shù)據(jù)中的噪聲。

模型復(fù)雜度和訓(xùn)練數(shù)據(jù)量:模型復(fù)雜度是指機器學(xué)習(xí)算法試圖的復(fù)雜度。模型的復(fù)雜度通常由訓(xùn)練數(shù)據(jù)決定:例如,如果使用少量數(shù)據(jù)來訓(xùn)練模型,那么低復(fù)雜度的模型更可取,這是因為高復(fù)雜度的模型會導(dǎo)致過擬合。

輸入空間的維度:在處理高維空間數(shù)據(jù)時,學(xué)習(xí)可能非常困難,因為會有許多額外的特征會混淆學(xué)習(xí)過程,也稱為維度災(zāi)難。因此,在處理高維空間數(shù)據(jù)時,常見的方法是修改學(xué)習(xí)算法,使其具有高偏差和低方差。

1.2 無監(jiān)督學(xué)習(xí)

在無監(jiān)督學(xué)習(xí)中,樣本集合缺少每個樣本對應(yīng)的輸出值(樣本集合沒有被標(biāo)記、分類或歸類)。無監(jiān)督學(xué)習(xí)的目標(biāo)是對樣本集合中的結(jié)構(gòu)或分布進行建模和推斷。因此,在無監(jiān)督學(xué)習(xí)中,算法利用數(shù)據(jù)中進行推斷,并試圖揭示其中的隱藏分布信息。聚類和降維是無監(jiān)督學(xué)習(xí)中最常用的兩種算法。

1.3 半監(jiān)督學(xué)習(xí)

半監(jiān)督學(xué)習(xí)可以看作是監(jiān)督學(xué)習(xí)和無監(jiān)督學(xué)習(xí)之間的折衷,因為它同時使用標(biāo)記和未標(biāo)記的數(shù)據(jù)進行訓(xùn)練。許多現(xiàn)實世界的機器學(xué)習(xí)問題可以歸類為半監(jiān)督,因為正確標(biāo)記所有數(shù)據(jù)可能非常困難或耗時,而未標(biāo)記的數(shù)據(jù)更容易收集。

2. K均值 (K-Means) 聚類

OpenCV 提供了 cv2.kmeans() 函數(shù)實現(xiàn) K-Means 聚類算法,該算法找到簇的中心并將輸入樣本分組到簇周圍。

K-Means 聚類算法的目標(biāo)是將 n 個樣本劃分(聚類)為 K 個簇,其中每個樣本都屬于具有最近均值的簇,cv2.kmeans() 函數(shù)用法如下:

retval, bestLabels, centers=cv.kmeans(data, K, bestLabels, criteria, attempts, flags[, centers])

data 表示用于聚類的輸入數(shù)據(jù),它是 np.float32 數(shù)據(jù)類型,每一列包含一個特征;K 指定最后需要的簇數(shù);算法終止標(biāo)準(zhǔn)由 criteria 參數(shù)指定,該參數(shù)設(shè)置最大迭代次數(shù)或所需精度,當(dāng)滿足這些標(biāo)準(zhǔn)時,算法終止。criteria 是具有三個參數(shù) (type, max_item, epsilon) 的元組:

criteria 參數(shù)的標(biāo)準(zhǔn)示例如下:

criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 1.0)

上述語句表示,最大迭代次數(shù)設(shè)置為 20 (max_iterm = 20),所需精度為 1.0 (epsilon = 1.0)。

attempts 參數(shù)指定使用不同的初始標(biāo)簽執(zhí)行算法的次數(shù)。flags 參數(shù)指定初始化簇中心的方法,其可選值包括:cv2.KMEANS_RANDOM_CENTERS 每次選擇隨機初始化簇中心;cv2.KMEANS_PP_CENTERS 使用 Arthur 等人提出的 K-Means++ 中心初始化。

cv2.kmeans() 返回以下內(nèi)容:

返回值 解釋
bestLabels 整數(shù)數(shù)組,用于存儲每個樣本的簇索引
center 包含每個簇中心的數(shù)組
compactness 每個點到其簇中心的距離平方和

2.1 K-Means 聚類示例

作為示例,我們將使用 K-Means 聚類算法對一組 2D 點進行聚類。這組 2D 點由 240 個點組成,使用兩個特征進行了描述:

# 2D數(shù)據(jù)
data = np.float32(np.vstack((np.random.randint(0, 50, (80, 2)), np.random.randint(40, 90, (80, 2)), np.random.randint(70, 110, (80, 2)))))
# 可視化
plt.scatter(data[:, 0], data[:, 1], c='c')
plt.show()

如上圖所示,數(shù)據(jù)將作為聚類算法的輸入,每個數(shù)據(jù)點有兩個特征對應(yīng)于 (x, y) 坐標(biāo),例如,這些坐標(biāo)可以表示 240 人人的身高和體重,而 K-Means 聚類算法用于決定衣服的尺寸(例如 K=3,則相應(yīng)表示尺寸為 S、M 或 L)。

接下來,我們將數(shù)據(jù)劃分為 2 個簇。第一步是定義算法終止標(biāo)準(zhǔn),將最大迭代次數(shù)設(shè)置為 20 (max_iterm = 20),epsilon 設(shè)置為 1.0 (epsilon = 1.0):

criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 1.0)

然后調(diào)用 cv2.kmeans() 函數(shù)應(yīng)用 K-Means 算法:

ret, label, center = cv2.kmeans(data, 2, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)

由于返回值 label 存儲每個樣本的聚類索引,因此,我們可以根據(jù) label 將數(shù)據(jù)拆分為不同的集群:

A = data[label.ravel() == 0]
B = data[label.ravel() == 1]

最后繪制 A 和 B 以及聚類前后的數(shù)據(jù),以便更好地理解聚類過程:

fig = plt.figure(figsize=(12, 6))
plt.suptitle("K-means clustering algorithm", fontsize=14,
fontweight='bold')
# 繪制原始數(shù)據(jù)
ax = plt.subplot(1, 2, 1)
plt.scatter(data[:, 0], data[:, 1], c='c')
plt.title("data")
# 繪制聚類后的數(shù)據(jù)和簇中心
ax = plt.subplot(1, 2, 2)
plt.scatter(A[:, 0], A[:, 1], c='b')
plt.scatter(B[:, 0], B[:, 1], c='g')
plt.scatter(center[:, 0], center[:, 1], s=100, c='m', marker='s')
plt.title("clustered data and centroids (K = 2)")
plt.show()

接下來,我們修改參數(shù) K 進行聚類并進行相應(yīng)的可視化。例如需要將數(shù)據(jù)分為三個簇,則首先應(yīng)用相同的過程對數(shù)據(jù)進行聚類,只需要修改參數(shù) (K=3) 將數(shù)據(jù)分為 3 個簇:

ret, label, center = cv2.kmeans(data, 3, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)

然后,當(dāng)使用標(biāo)簽輸出分離數(shù)據(jù)時,將數(shù)據(jù)分為三組:

A = data[label.ravel() == 0]
B = data[label.ravel() == 1]
C = data[label.ravel() == 2]

最后一步是顯示 A 、 B 和 C ,以及簇中心和訓(xùn)練數(shù)據(jù):

fig = plt.figure(figsize=(12, 6))
plt.suptitle("K-means clustering algorithm", fontsize=14,
fontweight='bold')
# 繪制原始數(shù)據(jù)
ax = plt.subplot(1, 2, 1)
plt.scatter(data[:, 0], data[:, 1], c='c')
plt.title("data")
# 繪制聚類后的數(shù)據(jù)和簇中心
ax = plt.subplot(1, 2, 2)
plt.scatter(A[:, 0], A[:, 1], c='b')
plt.scatter(B[:, 0], B[:, 1], c='g')
plt.scatter(C[:, 0], C[:, 1], c='r')
plt.scatter(center[:, 0], center[:, 1], s=100, c='m', marker='s')
plt.title("clustered data and centroids (K = 3)")
plt.show()

我們也可以將簇數(shù)設(shè)置為 4,觀察算法運行結(jié)果:

ret, label, center = cv2.kmeans(data, 4, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)

3. K最近鄰

k-最近鄰 (k-nearest neighbours, kNN) 是監(jiān)督學(xué)習(xí)中最簡單的算法之一,kNN 可用于分類和回歸問題。在訓(xùn)練階段,kNN 存儲所有訓(xùn)練樣本的特征向量和類別標(biāo)簽。在測試階段,將未標(biāo)記的向量分類為距離最近的 k 個訓(xùn)練樣本中出現(xiàn)頻率最高的類標(biāo)簽,其中 k 是用戶定義的常數(shù):

如上圖所示,如果 k = 5,則綠色圓圈(未標(biāo)記的測試樣本)將被歸類為三角形,因為離其最近的 5 個樣本中有 3 個三角形但只有 1 個菱形;如果 k = 9,則綠色圓圈將被歸類為菱形,因為離其最近的 9 個樣本中有 5 個菱形但只有 4 個三角形。

在 OpenCV 中,使用 kNN 分類器首先需要使用 cv2.ml.KNearest_create() 創(chuàng)建 kNN 分類器,然后提供數(shù)據(jù)和標(biāo)簽以使用 train() 方法訓(xùn)練 kNN分類器。最后,使用 findNearest() 方法用于查找測試樣本鄰居,使用如下:

retval, results, neighborResponses, dist=cv2.ml_KNearest.findNearest(samples, k[, results[, neighborResponses[, dist]]])

其中,samples 是輸入樣本,k 設(shè)置為最近鄰居的個數(shù),results 存儲每個輸入樣本的預(yù)測值,neighborResponses 存儲對應(yīng)的鄰居,dist 存儲輸入樣本到相應(yīng)鄰居的距離。

3.1 K最近鄰示例

接下來,為了演示 kNN 算法,首先隨機創(chuàng)建一組點并分配一個標(biāo)簽 (0 或 1)。標(biāo)簽 0 將代表紅色三角形,而標(biāo)簽 1 將代表藍色方塊;然后,使用 kNN 算法根據(jù) k 個最近鄰對樣本點進行分類。

第一步是創(chuàng)建具有相應(yīng)標(biāo)簽的點集和要分類的樣本點:

# 點集由50個點組成
data = np.random.randint(0, 100, (50, 2)).astype(np.float32)
# 為1每個點創(chuàng)建標(biāo)簽 (0:紅色, 1:藍色)
labels = np.random.randint(0, 2, (50, 1)).astype(np.float32)
# 創(chuàng)建要分類的樣本點
sample = np.random.randint(0, 100, (1, 2)).astype(np.float32)

接下來,創(chuàng)建 kNN 分類器,訓(xùn)練分類器,并找到要分類樣本點的 k 個最近鄰居:

# 創(chuàng)建 kNN 分類器
knn = cv2.ml.KNearest_create()
# 訓(xùn)練 kNN 分類器
knn.train(data, cv2.ml.ROW_SAMPLE, labels)
# 找到要分類樣本點的 k 個最近鄰居
k = 3
ret, results, neighbours, dist = knn.findNearest(sample, k)
# 打印結(jié)果
print("result: {}".format(results))
print("neighbours: {}".format(neighbours))
print("distance: {}".format(dist))

# 可視化
fig = plt.figure(figsize=(8, 6))
red_triangles = data[labels.ravel() == 0]
plt.scatter(red_triangles[:, 0], red_triangles[:, 1], 200, 'r', '^')
blue_squares = data[labels.ravel() == 1]
plt.scatter(blue_squares[:, 0], blue_squares[:, 1], 200, 'b', 's')
plt.scatter(sample[:, 0], sample[:, 1], 200, 'g', 'o')
plt.show()

獲得結(jié)果如下所示:

result: [[0.]]

neighbours: [[0. 0. 1.]]

distance: [[13. 40. 65.]]

因此,綠點被歸類為紅色三角形,可視化效果如下所示:

4. 支持向量機

支持向量機 (Support Vector Machine, SVM) 是一種監(jiān)督學(xué)習(xí)技術(shù),它通過根據(jù)指定的類對訓(xùn)練數(shù)據(jù)進行最佳分離,從而在高維空間中構(gòu)建一個或一組超平面。

已二維平面為例,在下圖中看到,其中綠線是能夠?qū)蓚€類分開的最佳超平面,因為其到兩個類中的最近元素的距離是最大的:

上圖第一種情況下,決策邊界是一條線,而在第二種情況下,決策邊界是一條圓形曲線,虛線代表其他決策邊界,但它們并非最好地將兩個類分開的決策邊界。

OpenCV 中的 SVM 實現(xiàn)基于 LIBSVM,使用 cv2.ml.SVM_create() 函數(shù)創(chuàng)建空模型,然后為模型分配主要參數(shù):

svmType :設(shè)置 SVM 類型,可選值如下:

  • SVM_C_SVC:C CC-支持向量分類,可用于 n 分類 (n≥2) 問題
  • NU_SVC: v vv-支持向量分類
  • ONE_CLASS: 分布估計(單類 SVM)
  • EPS_SVR: ? \epsilon?-支持向量回歸
  • NU_SVR: v vv-支持向量回歸

kernelType :這設(shè)置了 SVM 的核類型,可選值如下:

  • LINEAR : 線性核
  • POLY :多項式核
  • RBF : Radial Basis Function (RBF),大多數(shù)情況下是不錯的選擇
  • SIGMOID : Sigmoid 核
  • CHI2 : 指數(shù) Chi2 核,類似于 RBF 核
  • INTER : 直方圖交集核;運行速度較快的核

degree : 核函數(shù)的 degree 參數(shù) (用于 POLY 核)

gamma :核函數(shù)的 γ \gammaγ 參數(shù)(用于 POLY/RBF/SIGMOID/CHI2 核)

coef0 : 核函數(shù)的 coef0 參數(shù) (用于 POLY/SIGMOID 核)

Cvalue : SVM 優(yōu)化問題的 C 參數(shù) (用于 C_SVC/EPS_SVR/NU_SVR 類型)

nu : SVM 優(yōu)化問題的 v vv 參數(shù) (用于 NU_SVC/ONE_CLASS/NU_SVR 類型)

p : SVM 優(yōu)化問題的 ? \epsilon? 參數(shù) (用于 EPS_SVR 類型)

classWeights : C_SVC 問題中的可選權(quán)重,分配給特定的類

termCrit :迭代 SVM 訓(xùn)練過程的終止標(biāo)準(zhǔn)

核函數(shù)選擇通常取決于數(shù)據(jù)集,通常可以首先使用 RBF 核進行測試,因為該核將樣本非線性地映射到更高維空間,可以方便的處理類標(biāo)簽和屬性之間的關(guān)系是非線性的情況。

默認構(gòu)造函數(shù)使用以下值初始化 SVM:

svmType: C_SVC, kernelType: RBF, degree: 0, gamma: 1, coef0: 0, C: 1, nu: 0, p: 0, classWeights: 0, termCrit: TermCriteria(MAX_ITER+EPS, 1000, FLT_EPSILON )

4.1 支持向量機示例

為了解如何在 OpenCV 中使用 SVM,首先需要創(chuàng)建訓(xùn)練數(shù)據(jù)和標(biāo)簽:

labels = np.array([1, 1, -1, -1, -1])
data = np.matrix([[800, 40], [850, 400], [500, 10], [550, 300], [450, 600]], dtype=np.float32)

以上代碼創(chuàng)建了 5 個點,前 2 個點被指定為 1 類,而另外 3 個被指定為 -1 類。接下來使用 svm_init() 函數(shù)初始化 SVM 模型:

def svm_init(C=12.5, gamma=0.50625):
    """ 創(chuàng)建 SVM 模型并為其分配主要參數(shù),返回模型 """
    model = cv2.ml.SVM_create()
    model.setGamma(gamma)
    model.setC(C)
    model.setKernel(cv2.ml.SVM_LINEAR)
    model.setType(cv2.ml.SVM_C_SVC)
    model.setTermCriteria((cv2.TERM_CRITERIA_MAX_ITER, 100, 1e-6))
    return model
# 初始化 SVM 模型
svm_model = svm_init(C=12.5, gamma=0.50625)

創(chuàng)建的 SVM 核類型設(shè)置為 LINEAR,SVM 的類型設(shè)置為 C_SVC。

然后,編寫 svm_train() 函數(shù)訓(xùn)練 SVM 模型:

def svm_train(model, samples, responses):
    # 使用 samples 和 responses 訓(xùn)練模型
    model.train(samples, cv2.ml.ROW_SAMPLE, responses)
    return model
# 訓(xùn)練 SVM
svm_train(svm_model, data, labels)

然后創(chuàng)建一個圖像,并繪制 SVM 響應(yīng):

def show_svm_response(model, image):

    colors = {1: (255, 255, 0), -1: (0, 255, 255)}

    for i in range(image.shape[0]):
        for j in range(image.shape[1]):
            sample = np.matrix([[j, i]], dtype=np.float32)
            response = svm_predict(model, sample)

            image[i, j] = colors[response.item(0)]
    
    cv2.circle(image, (800, 40), 10, (255, 0, 0), -1)
    cv2.circle(image, (850, 400), 10, (255, 0, 0), -1)

    cv2.circle(image, (500, 10), 10, (0, 255, 0), -1)
    cv2.circle(image, (550, 300), 10, (0, 255, 0), -1)
    cv2.circle(image, (450, 600), 10, (0, 255, 0), -1)

    support_vectors = model.getUncompressedSupportVectors()
    for i in range(support_vectors.shape[0]):
        cv2.circle(image, (support_vectors[i, 0], support_vectors[i, 1]), 15, (0, 0, 255), 6)
# 創(chuàng)建圖像
img_output = np.zeros((640, 1200, 3), dtype="uint8")
# 顯示 SVM 響應(yīng)
show_svm_response(svm_model, img_output)

如上圖所示,SVM 使用訓(xùn)練數(shù)據(jù)進行了訓(xùn)練,可用于對圖像中所有點進行分類。SVM 將圖像劃分為黃色和青色區(qū)域,可以看到兩個區(qū)域之間的邊界對應(yīng)于兩個類之間的最佳間隔,因為到兩個類中最近元素的距離最大,支持向量用紅線邊框顯示。

小結(jié)

在本文中,首先介紹機器學(xué)習(xí)的概念及其相關(guān)話題,然后總結(jié)了機器學(xué)習(xí)中的三種主要方法,并總結(jié)了分類、回歸和聚類問題的三種最常見的技術(shù)。最后,我們通過示例了解了常用機器學(xué)習(xí)算法,具體而言,包括 K-Means 聚類算法、kNN 算法和 SVM 算法。?

以上就是Python OpenCV實戰(zhàn)之與機器學(xué)習(xí)的碰撞的詳細內(nèi)容,更多關(guān)于OpenCV 機器學(xué)習(xí)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論