日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人工智能 > ChatGpt >内容正文

ChatGpt

词袋模型 matlab,【火炉炼AI】机器学习051-视觉词袋模型+极端随机森林建立图像分类器...

發(fā)布時間:2024/1/8 ChatGpt 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 词袋模型 matlab,【火炉炼AI】机器学习051-视觉词袋模型+极端随机森林建立图像分类器... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

【火爐煉AI】機(jī)器學(xué)習(xí)051-視覺詞袋模型+極端隨機(jī)森林建立圖像分類器

(本文所使用的Python庫和版本號: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )

視覺詞袋模型(Bag Of Visual Words,BOVW)來源于自然語言處理中的詞袋模型(Bag Of Words, BOW),關(guān)于詞袋模型,可以參考我的博文【火爐煉AI】機(jī)器學(xué)習(xí)038-NLP創(chuàng)建詞袋模型.在NLP中,BOW的核心思想是將一個文檔當(dāng)做一個袋子,里面裝著各種各樣的單詞,根據(jù)單詞出現(xiàn)的頻次或權(quán)重來衡量某個單詞的重要性。BOW的一個重要特性是不考慮單詞出現(xiàn)的順序,句子語法等因素。

視覺詞袋模型BOVW是將BOW的核心思想應(yīng)用于圖像處理領(lǐng)域的一種方法,為了表示一幅圖像,我們可以將圖像看做文檔,即若干個“視覺單詞”的集合,和BOW一樣,不考慮這些視覺單詞出現(xiàn)的順序,故而BOVW的一個缺點是忽視了像素之間的空間位置信息(當(dāng)然,針對這個缺點有很多改進(jìn)版本)。BOVW的核心思想可以從下圖中看出一二。

image

有人要問了,提取圖像的特征方法有很多,比如SIFT特征提取器,Star特征提取器等,為什么還要使用BOVW模型來表征圖像了?因為SIFT,Star這些特征提取器得到的特征矢量是多維的,比如SIFT矢量是128維,而且一幅圖像通常會包含成百上千個SIFT矢量,在進(jìn)行下游機(jī)器學(xué)習(xí)計算時,這個計算量非常大,效率很低,故而通常的做法是用聚類算法對這些特征矢量進(jìn)行聚類,然后用聚類中的一個簇代表BOVW中的一個視覺單詞,將同一幅圖像的SIFT矢量映射到視覺視覺單詞序列,生成視覺碼本,這樣,每一幅圖像都可以用一個視覺碼本矢量來描述,在后續(xù)的計算中,效率大大提高,有助于大規(guī)模的圖像檢索。

1. 使用BOVW建立圖像數(shù)據(jù)集

BOVW主要包括三個關(guān)鍵步驟:

1,提取圖像特征:提取算法可以使用SIFT,Star,HOG等方法,比如使用SIFT特征提取器,對數(shù)據(jù)集中的每一幅圖像都使用SIFT后,每一個SIFT特征用一個128維描述特征向量表示,假如有M幅圖像,一共提取出N個SIFT特征向量。

2,聚類得到視覺單詞:最常用的是K-means,當(dāng)然可以用其他聚類算法,使用聚類對N個SIFT特征向量進(jìn)行聚類,K-means會將N個特征向量分成K個簇,使得每個簇內(nèi)部的特征向量都具有非常高的相似度,而簇間的相似度較低,聚類后會得到K個聚類中心(在BOVW中,聚類中心被稱為視覺單詞)。計算每一幅圖像的每一個SIFT特征到這K個視覺單詞的距離,并將其映射到距離最近的一個簇中(即該視覺單詞的對應(yīng)詞頻+1)。這樣,每一幅圖像都變成了一個與視覺單詞相對應(yīng)的詞頻矢量。

3,構(gòu)建視覺碼本:因為每一幅圖像的SIFT特征個數(shù)不相等,所以需要對這些詞頻矢量進(jìn)行歸一化,將每幅圖像的SIFT特征個數(shù)變?yōu)轭l數(shù),這樣就得到視覺碼本。

整個流程可以簡單地用下圖描述:

image

下面開始準(zhǔn)備數(shù)據(jù)集,首先從Caltech256圖像抽取3類,每一類隨機(jī)抽取20張圖片,組成一個小型數(shù)據(jù)集,每一個類別放在一個文件夾中,且文件夾的命名以數(shù)字和“-”開頭,數(shù)字就表示類別名稱。這個小數(shù)據(jù)集純粹是驗證算法是否能跑通。如下為準(zhǔn)備的數(shù)據(jù)集:

image

首先來看第一步的代碼:提取圖像特征的代碼:

def __img_sift_features(self,image):

'''

提取圖片image中的Star特征的關(guān)鍵點,然后用SIFT特征提取器進(jìn)行計算,

得到N行128列的矩陣,每幅圖中提取的Star特征個數(shù)不一樣,故而N不一樣,

但是經(jīng)過SIFT計算之后,特征的維度都變成128維。

返回該N行128列的矩陣

'''

keypoints=xfeatures2d.StarDetector_create().detect(image)

gray=cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

_,feature_vectors=xfeatures2d.SIFT_create().compute(gray,keypoints)

return feature_vectors

然后將得到的所有圖片的N行128列特征集合起來,組成M行128列特征,構(gòu)建一個聚類算法,用這個算法來映射得到含有32個聚類中心(視覺單詞)的模型,將這128列特征映射到32個視覺單詞中(由于此處Kmeans我使用32個簇,故而得到32個視覺單詞,越復(fù)雜的項目,這個值要調(diào)整的越大,從幾百到幾千不等。),在統(tǒng)計每一個特征出現(xiàn)的頻次,組成一個詞袋模型,如下代碼:

def __map_feature_to_cluster(self,img_path):

'''從單張圖片中提取Star特征矩陣(N行128列),

再將該特征矩陣通過K-means聚類算法映射到K個類別中,每一行特征映射到一個簇中,得到N個簇標(biāo)號的向量,

統(tǒng)計每一個簇中出現(xiàn)的特征向量的個數(shù),相當(dāng)于統(tǒng)計詞袋中某個單詞出現(xiàn)的頻次。

'''

img_feature_vectors=self.__img_sift_features(self.__get_image(img_path)) # N 行128列

cluster_labels=self.cluster_model.predict(img_feature_vectors)

# 計算這些特征在K個簇中的類別,得到N個數(shù)字,每個數(shù)字是0-31中的某一個,代表該Star特征屬于哪一個簇

# eg [30 30 30 6 30 30 23 25 23 23 30 30 16 17 31 30 30 30 4 25]

# 統(tǒng)計每個簇中特征的個數(shù)

vector_nums=np.zeros(self.clusters_num) # 32個元素

for num in cluster_labels:

vector_nums[num]+=1

# 將特征個數(shù)歸一化處理:得到百分比而非個數(shù)

sum_=sum(vector_nums)

return [vector_nums/sum_] if sum_>0 else [vector_nums] # 一行32列,32 個元素組成的list

上面僅僅是用一部分圖片來得到聚類中心,沒有用全部的圖像,因為部分圖像完全可以代表全部圖像。

第三步:獲取多張圖片的視覺碼本,將這些視覺碼本組成一個P行32列的矩陣。

def __calc_imgs_clusters(self,img_path_list):

'''獲取多張圖片的視覺碼本,將這些視覺碼本組成一個P行32列的矩陣,P是圖片張數(shù),32是聚類的類別數(shù)。

返回該P(yáng)行32列的矩陣'''

img_paths=list(itertools.chain(*img_path_list)) # 將多層list展開

code_books=[]

[code_books.extend(self.__map_feature_to_cluster(img_path)) for img_path in img_paths]

return code_books

完整的準(zhǔn)備數(shù)據(jù)集的代碼比較長,如下:

# 準(zhǔn)備數(shù)據(jù)集

import cv2,itertools,pickle,os

from cv2 import xfeatures2d

from glob import glob

class DataSet:

def __init__(self,img_folder,cluster_model_path,img_ext='jpg',max_samples=12,clusters_num=32):

self.img_folder=img_folder

self.cluster_model_path=cluster_model_path

self.img_ext=img_ext

self.max_samples=max_samples

self.clusters_num=clusters_num

self.img_paths=self.__get_img_paths()

self.all_img_paths=[list(item.values())[0] for item in self.img_paths]

self.cluster_model=self.__load_cluster_model()

def __get_img_paths(self):

folders=glob(self.img_folder+'/*-*') # 由于圖片文件夾的名稱是數(shù)字+‘-’開頭,故而可以用這個來獲取

img_paths=[]

for folder in folders:

class_label=folder.split('\\')[-1]

img_paths.append({class_label:glob(folder+'/*.'+self.img_ext)})

# 每一個元素都是一個dict,key為文件夾名稱,value為該文件夾下所有圖片的路徑組成的list

return img_paths

def __get_image(self,img_path,new_size=200):

def resize_img(image,new_size):

'''將image的長或?qū)捴械淖钚≈嫡{(diào)整到new_size'''

h,w=image.shape[:2]

ratio=new_size/min(h,w)

return cv2.resize(image,(int(w*ratio),int(h*ratio)))

image=cv2.imread(img_path)

return resize_img(image,new_size)

def __img_sift_features(self,image):

'''

提取圖片image中的Star特征的關(guān)鍵點,然后用SIFT特征提取器進(jìn)行計算,

得到N行128列的矩陣,每幅圖中提取的Star特征個數(shù)不一樣,故而N不一樣,

但是經(jīng)過SIFT計算之后,特征的維度都變成128維。

返回該N行128列的矩陣

'''

keypoints=xfeatures2d.StarDetector_create().detect(image)

gray=cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

_,feature_vectors=xfeatures2d.SIFT_create().compute(gray,keypoints)

return feature_vectors

def __calc_imgs_features(self,img_path_list):

'''獲取多張圖片的特征矢量,這些特征矢量是合并到一起的,最終組成M行128列的矩陣,返回該矩陣.

此處的M是每張圖片的特征矢量個數(shù)之和,即N1+N2+N3....'''

img_paths=list(itertools.chain(*img_path_list)) # 將多層list展開

feature_vectors=[]

[feature_vectors.extend(self.__img_sift_features(self.__get_image(img_path))) for img_path in img_paths]

return feature_vectors

def __create_save_Cluster(self):

'''由于folders中含有大量圖片,故而取一小部分(max_samples)圖片來做K-means聚類。

'''

# 獲取要進(jìn)行聚類的小部分圖片的路徑

cluster_img_paths=[list(item.values())[0][:self.max_samples] for item in self.img_paths]

feature_vectors=self.__calc_imgs_features(cluster_img_paths)

cluster_model = KMeans(self.clusters_num, # 建立聚類模型

n_init=10,

max_iter=10, tol=1.0)

cluster_model.fit(feature_vectors) # 對聚類模型進(jìn)行訓(xùn)練

# 將聚類模型保存,以后就不需要再訓(xùn)練了。

with open(self.cluster_model_path,'wb+') as file:

pickle.dump(cluster_model,file)

print('cluster model is saved to {}.'.format(self.cluster_model_path))

return cluster_model

def __map_feature_to_cluster(self,img_path):

'''從單張圖片中提取Star特征矩陣(N行128列),

再將該特征矩陣通過K-means聚類算法映射到K個類別中,每一行特征映射到一個簇中,得到N個簇標(biāo)號的向量,

統(tǒng)計每一個簇中出現(xiàn)的特征向量的個數(shù),相當(dāng)于統(tǒng)計詞袋中某個單詞出現(xiàn)的頻次。

'''

img_feature_vectors=self.__img_sift_features(self.__get_image(img_path)) # N 行128列

cluster_labels=self.cluster_model.predict(img_feature_vectors)

# 計算這些特征在K個簇中的類別,得到N個數(shù)字,每個數(shù)字是0-31中的某一個,代表該Star特征屬于哪一個簇

# eg [30 30 30 6 30 30 23 25 23 23 30 30 16 17 31 30 30 30 4 25]

# 統(tǒng)計每個簇中特征的個數(shù)

vector_nums=np.zeros(self.clusters_num) # 32個元素

for num in cluster_labels:

vector_nums[num]+=1

# 將特征個數(shù)歸一化處理:得到百分比而非個數(shù)

sum_=sum(vector_nums)

return [vector_nums/sum_] if sum_>0 else [vector_nums] # 一行32列,32 個元素組成的list

def __calc_imgs_clusters(self,img_path_list):

'''獲取多張圖片的視覺碼本,將這些視覺碼本組成一個P行32列的矩陣,P是圖片張數(shù),32是聚類的類別數(shù)。

返回該P(yáng)行32列的矩陣'''

img_paths=list(itertools.chain(*img_path_list)) # 將多層list展開

code_books=[]

[code_books.extend(self.__map_feature_to_cluster(img_path)) for img_path in img_paths]

return code_books

def __load_cluster_model(self):

'''從cluster_model_path中加載聚類模型,返回該模型,如果不存在或出錯,則調(diào)用函數(shù)準(zhǔn)備聚類模型'''

cluster_model=None

if os.path.exists(self.cluster_model_path):

try:

with open(self.cluster_model_path, 'rb') as f:

cluster_model = pickle.load(f)

except:

pass

if cluster_model is None:

print('No valid model found, start to prepare model...')

cluster_model=self.__create_save_Cluster()

return cluster_model

def get_img_code_book(self,img_path):

'''獲取單張圖片的視覺碼本,即一行32列的list,每個元素都是對應(yīng)特征出現(xiàn)的頻率'''

return self.__map_feature_to_cluster(img_path)

def get_imgs_code_books(self,img_path_list):

'''獲取多張圖片的視覺碼本,即P行32列的list,每個元素都是對應(yīng)特征出現(xiàn)的頻率'''

return self.__calc_imgs_clusters(img_path_list)

def get_all_img_code_books(self):

'''獲取img_folder中所有圖片的視覺碼本'''

return self.__calc_imgs_clusters(self.all_img_paths)

def get_img_labels(self):

'''獲取img_folder中所有圖片對應(yīng)的label,可以從文件夾名稱中獲取'''

img_paths=list(itertools.chain(*self.all_img_paths))

return [img_path.rpartition('-')[0].rpartition('\\')[2] for img_path in img_paths]

def prepare_dataset(self):

'''獲取img_folder中所有圖片的視覺碼本和label,構(gòu)成數(shù)據(jù)集'''

features=self.get_all_img_code_books()

labels=self.get_img_labels()

return np.c_[features,labels]

2. 使用極端隨機(jī)森林建立模型

極端隨機(jī)森林是隨機(jī)森林算法的一個提升版本,可以參考我以前的文章【火爐煉AI】機(jī)器學(xué)習(xí)007-用隨機(jī)森林構(gòu)建共享單車需求預(yù)測模型.使用方法和隨機(jī)森林幾乎一樣。

# 極端隨機(jī)森林分類器

from sklearn.ensemble import ExtraTreesClassifier

class CLF_Model:

def __init__(self,n_estimators=100,max_depth=16):

self.model=ExtraTreesClassifier(n_estimators=n_estimators,

max_depth=max_depth, random_state=12)

def fit(self,train_X,train_y):

self.model.fit(train_X,train_y)

def predict(self,newSample_X):

return self.model.predict(newSample_X)

其實,這個分類器很簡單,沒必要寫成類的形式。

對該分類器進(jìn)行訓(xùn)練:

dataset_df=pd.read_csv('./prepared_set.txt',index_col=[0])

dataset_X,dataset_y=dataset_df.iloc[:,:-1].values,dataset_df.iloc[:,-1].values

model=CLF_Model()

model.fit(dataset_X,dataset_y)

3. 使用訓(xùn)練后模型預(yù)測新樣本

如下,我隨機(jī)測試三張圖片,均得到了比較好的結(jié)果。

# 用訓(xùn)練好的model預(yù)測新圖片,看看它屬于哪一類

new_img1='E:\PyProjects\DataSet\FireAI/test0.jpg'

img_code_book=dataset.get_img_code_book(new_img1)

predicted=model.predict(img_code_book)

print(predicted)

new_img2='E:\PyProjects\DataSet\FireAI/test1.jpg'

img_code_book=dataset.get_img_code_book(new_img2)

predicted=model.predict(img_code_book)

print(predicted)

new_img3='E:\PyProjects\DataSet\FireAI/test2.jpg'

img_code_book=dataset.get_img_code_book(new_img3)

predicted=model.predict(img_code_book)

print(predicted)

-------------------------------------輸---------出--------------------------------

[0]

[1]

[2]

--------------------------------------------完-------------------------------------

########################小**********結(jié)###############################

1,這個項目的難點在于視覺詞袋模型的理解和數(shù)據(jù)集準(zhǔn)備,所以我將其寫成了類的形式,這個類具有一定的通用性,可以用于其他項目數(shù)據(jù)集的制備。

2,從這個項目可以看出視覺詞袋模型相對于原始的Star特征的優(yōu)勢:如果使用原來的Star特征,一張圖片會得到N行128列的特征數(shù),而使用了BOVW模型,我們將N行128列的特征數(shù)據(jù)映射到1行32列的空間中,所以極大的降低了特征數(shù),使得模型簡化,訓(xùn)練和預(yù)測效率提高。

3,一旦準(zhǔn)備好了數(shù)據(jù)集,就可以用各種常規(guī)的機(jī)器學(xué)習(xí)分類器進(jìn)行分類,也可以用各種方法評估該分類器的優(yōu)劣,比如性能報告,準(zhǔn)確率,召回率等,由于這部分我在前面的文章中已經(jīng)講過多次,故而此處省略。

#################################################################

注:本部分代碼已經(jīng)全部上傳到(我的github)上,歡迎下載。

參考資料:

1, Python機(jī)器學(xué)習(xí)經(jīng)典實例,Prateek Joshi著,陶俊杰,陳小莉譯

總結(jié)

以上是生活随笔為你收集整理的词袋模型 matlab,【火炉炼AI】机器学习051-视觉词袋模型+极端随机森林建立图像分类器...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。