發布時間: 2019-09-25 14:13:40
舉個簡單的例子,我們可以使用k-近鄰算法分類一個電影是愛情片還是動作片。
上表就是我們已有的數據集合,也就是訓練樣本集。這個數據集有兩個特征,即打斗鏡頭數和接吻鏡頭數。除此之外,我們也知道每個電影的所屬類型,即分類標簽。用肉眼粗略地觀察,接吻鏡頭多的,是愛情片。打斗鏡頭多的,是動作片。以我們多年的看片經驗,這個分類還算合理。如果現在給我一部電影,你告訴我這個電影打斗鏡頭數和接吻鏡頭數。不告訴我這個電影類型,我可以根據你給我的信息進行判斷,這個電影是屬于愛情片還是動作片。而k-近鄰算法也可以像我們人一樣做到這一點,不同的地方在于,我們的經驗更”牛逼”,而k-鄰近算法是靠已有的數據。比如,你告訴我這個電影打斗鏡頭數為2,接吻鏡頭數為102,我的經驗會告訴你這個是愛情片,k-近鄰算法也會告訴你這個是愛情片。你又告訴我另一個電影打斗鏡頭數為49,接吻鏡頭數為51,我”邪惡”的經驗可能會告訴你,這有可能是個”愛情動作片”,畫面太美,我不敢想象。 (如果說,你不知道”愛情動作片”是什么?請評論留言與我聯系,我需要你這樣像我一樣純潔的朋友。) 但是k-近鄰算法不會告訴你這些,因為在它的眼里,電影類型只有愛情片和動作片,它會提取樣本集中特征最相似數據(最鄰近)的分類標簽,得到的結果可能是愛情片,也可能是動作片,但絕不會是”愛情動作片”。當然,這些取決于數據集的大小以及最近鄰的判斷標準等因素。
2.距離度量
我們已經知道k-近鄰算法根據特征比較,然后提取樣本集中特征最相似數據(最鄰近)的分類標簽。那么,如何進行比較呢?比如,我們還是以表2為例,怎么判斷紅色圓點標記的電影所屬的類別呢?如下圖所示:
圖2?
??
通過計算可知,紅色圓點標記的電影到動作片 (108,5)的距離最近,為16.55。如果算法直接根據這個結果,判斷該紅色圓點標記的電影為動作片,這個算法就是最近鄰算法,而非k-近鄰算法。那么k-鄰近算法是什么呢?k-近鄰算法步驟如下:
1.計算已知類別數據集中的點與當前點之間的距離;
2.按照距離遞增次序排序;
3.選取與當前點距離最小的k個點;
4.確定前k個點所在類別的出現頻率;
5.返回前k個點所出現頻率較高的類別作為當前點的預測分類。
比如,現在我這個k值取3,那么在電影例子中,按距離依次排序的三個點分別是動作片(108,5)、動作片(115,8)、愛情片(5,89)。在這三個點中,動作片出現的頻率為三分之二,愛情片出現的頻率為三分之一,所以該紅色圓點標記的電影為動作片。這個判別過程就是k-近鄰算法。
3.k近鄰算法實例-預測入住位置??
import pandas as pd from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.neighbors import KNeighborsClassifier from sklearn.preprocessing import StandardScaler ''' k近鄰 ''' def knncl(): #讀取數據 data = pd.read_csv("../data/train.csv") #處理數據,選擇一部分數據 data = data.query("x>1.0 & x <1.25 & y>2.5 & y<2.75") #處理時間戳 2016-10-21 20:30:00 time_value = pd.to_datetime(data["time"]) #將時間轉成日歷的格式 {"day":...,"hour":...} time_value = pd.DatetimeIndex(time_value) #增加日期、小時、星期等幾個特征 data["day"] = time_value.day data["hour"] = time_value.hour data["weekday"] = time_value.weekday # 把時間戳特征刪除 data = data.drop(["time"],axis=1) # 按place_id分組,統計每個位置的入住次數 place_count = data.groupby("place_id").count() # print(place_count) # reset_index()將place_id單獨一列 tf = place_count[place_count.row_id > 3].reset_index() # 把簽到數據少于n個目標位置刪除 data = data[data['place_id'].isin(tf.place_id)] # 取出數據中的特征值的目標值 y = data['place_id'] x = data.drop(['place_id'], axis=1) # 數據集分割,分成訓練集和測試集 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25) # 特征工程,標準化處理 std = StandardScaler() # 對測試集和訓練集的特征值進行標準化 x_train = std.fit_transform(x_train) x_test = std.transform(x_test) print(data.head(10)) # 進行算法流程 # 超參數 knn = KNeighborsClassifier() knn.fit(x_train, y_train) y_predict = knn.predict(x_test) print("預測的目標簽到位置為:", y_predict) # 得出準確率 print("預測的準確率:", knn.score(x_test, y_test)) #進行算法流程 # 超參數 #網絡搜索 # params = {"n_neighbors":[3,5,10]} # gc = GridSearchCV(knn,param_grid=params,cv=2) # gc.fit(x_train,y_train) # # #預測數據 # print("在測試集上準確率:", gc.score(x_test, y_test)) # print("在交叉驗證當中最好的結果:", gc.best_score_) # print("選擇最好的模型是:", gc.best_estimator_) # print("每個超參數每次交叉驗證的結果:", gc.cv_results_) return None if __name__ == "__main__": knncl() |