機器學習實戰——1.1K近鄰演算法
阿新 • • 發佈:2018-12-26
宣告:參考書目《機器學習實戰》作者: Peter Harrington 出版社: 人民郵電出版社 譯者: 李銳 / 李鵬 / 曲亞東 / 王斌
參考部落格 Jack-Cui 作者個人網站:http://cuijiahua.com/
公式:
K近鄰演算法的一般步驟
- 收集資料:可以使用任何方法
- 準備資料:使用Python解析、預處理資料。
- 分析資料:可以使用很多方法對資料進行分析,例如使用Matplotlib將資料視覺化。
- 測試演算法:計算錯誤率。
- 使用演算法:錯誤率在可接受範圍內,就可以執行k-近鄰演算法進行分類。
海倫女士一直使用線上約會網站尋找適合自己的約會物件。儘管約會網站會推薦不同的任選,但她並不是喜歡每一個人。經過一番總結,她發現自己交往過的人可以進行如下分類:
- 不喜歡的人
- 魅力一般的人
- 極具魅力的人
海倫收集約會資料已經有了一段時間,她把這些資料存放在文字檔案datingTestSet.txt中,每個樣本資料佔據一行,總共有1000行。資料地址:DataSet。
資料主要包括四行,三種特徵以及一個標籤:其中第一組資料數量級遠大於其他兩組資料,如果直接將原始資料放入公式 會導致第一組資料其決定性的作用,從而導致其他兩組資料失效。因此我們需要將原始資料進行歸一化處理,將所有資料都處理到0-1的區間內。公式: 。
所以我們的目的這次就很清楚了,
- 首先將資料從文字匯入,進行預處理,將其放置到矩陣中
- 將矩陣中的資料進行歸一化處理
- 將需要進行判斷的資料輸入,並與DataSet中所有資料進行歐式距離計算
- 選取歐氏距離最小的前 k 個數據,將其中距離最小的資料你的類別作為本次輸入資料的類別
#-*-cording:UTF-8-*- import numpy as np #將資料從文字讀入矩陣中 filename 為檔案所在的地址 def ReadFile(filename): #開啟文字並讀取文字中的內容 fr = open(filename) ReadLines = fr.readlines() #記錄文字行數是為了建立一個可以正好放入所有資料的矩陣 Len_File = len(ReadLines) #建立一個全零矩陣大小為 Len_File * 3 Array_return = np.zeros((Len_File,3)) #建立一個列表,用於存放標籤 ClassLables = [] #index用於記錄存放在數組裡面數據的位置的 index = 0 #逐行讀取文字內容 for line in ReadLines: #去除空格跟換行符 line = line.strip() line = line.split('\t') #將每行資料的前三個賦值給矩陣對應的行。資料第四個為標籤 Array_return[index, : ] = line[0:3] #按標籤將資料進行分類,1代表不喜歡,2第還行,3表示還不錯 if line[-1] == 'didntLike': ClassLables.append(1) elif line[-1] == 'smallDoses': ClassLables.append(2) elif line[-1] == 'largeDoses': ClassLables.append(3) index += 1 return Array_return, ClassLables #歸一化處理 DataSet為輸入的資料集 #公式為 newValue= (oleValue - min)/(max - min) def AutoNorm(DataSet): #shape[0]返回的是Dataset的行數,shape[1]返回的是列數 array_len = DataSet.shape[0] #輸出DataSet行裡面的最大最小值 min_value = DataSet.min(axis=0) max_value = DataSet.max(axis=0) value_range = max_value - min_value #newArray = np.zeros(np.shape(DataSet)) #np.tile 是將min_value在行方向上覆制 array_len 次,在列方向上覆制1 次 newArray = DataSet - np.tile(min_value,(array_len,1)) newArray = newArray / np.tile(value_range,(array_len,1)) return newArray,value_range, min_value #K近鄰處理演算法 #公式為 diatance ={ (x1-x2)^2 - (y1-y2)^2 }^0.5 #Data為你給的資料,DataSet為資料集,Labes為標籤,K為你選擇的樣本數 def Classify(Data, DataSet, Lables, k): #獲取DataSet的行數,用以建立矩陣 LenData = DataSet.shape[0] #建立一個矩陣,這個矩陣是由你給的 1*3矩陣複製成 LenData*3的矩陣減去DataSet矩陣得到的 ArryMat = np.tile(Data, (LenData, 1)) - DataSet #將矩陣開方,其實是將矩陣內每個元素進行開方處理 SqlMat = ArryMat ** 2 #將矩陣按照列方向進行相加,變成一個LenData*1的矩陣 SumMat = SqlMat.sum(axis=1) #將矩陣開根號處理 DistanceMat = SumMat ** 0.5 #將矩陣元素按從小到大排序,即數值越小說明距離越短,也就是越接近這個類別 SortDistance = DistanceMat.argsort() #建立一個字典用來存放對應類別的個數 ClassCount = {} for i in range(k): #返回Lables votoLables = Lables[SortDistance[i]] #字典的get函式dict.get(key, default=None)如果沒有找到對應的值,那麼就會返回你設定的值,或者預設值。這裡我們設定為 0 ClassCount[votoLables] = ClassCount.get(votoLables,0) + 1 #將字典裡按照從大到小排序 SortClassCount = sorted(ClassCount.items(), reverse=True) #返回最大值 return SortClassCount[0][0] if __name__ == "__main__": filename = "C:/Users/lpp/Desktop/datingTestSet.txt" DataSet, Lables = ReadFile(filename) Array, value_range, min_value = AutoNorm(DataSet) precentTats = float(input("玩視訊遊戲所耗時間百分比:")) ffMiles = float(input("每年獲得的飛行常客里程數:")) iceCream = float(input("每週消費的冰激淋公升數:")) data = np.array([precentTats, ffMiles, iceCream]) ClassCount = Classify(data, Array, Lables, 1) if ClassCount == 1: print("不喜歡") elif ClassCount == 2: print("感興趣") elif ClassCount == 3: print("非常喜歡")