什么是K-臨近算法
測量不同特征值之間的距離方法進行分類
工作原理
- 存在一個訓練樣本集即舌,樣本集中每一數(shù)據(jù)與所屬分類的對應關系
- 輸入沒有標簽的新數(shù)據(jù)后昔园,將新數(shù)據(jù)的每個特征與樣本集中數(shù)據(jù)對應的 特征進行比較,然后算法提取樣本集中特征最相似數(shù)據(jù)(最近鄰)的分類標簽
- 通常k是不大于20的整數(shù)芽淡, 最后,選擇k個最相似數(shù)據(jù)中出現(xiàn)次數(shù)最多的分類,作為新數(shù)據(jù)的分類
例子
使用打斗和接吻鏡頭數(shù)分類電影
問號位置是該未知電影出現(xiàn)的鏡頭數(shù)圖形化展示
計算未知電影 與樣本集中其他電影的距離
按照距離遞增排序鸡典,可以找到k個距離最近的電影
假定k=3,則三個最靠近的電影依次是He’s Not Really into Dudes枪芒、Beautiful Woman 和California Man彻况。k-近鄰算法按照距離最近的三部電影的類型,決定未知電影的類型舅踪,而這三部 電影全是愛情片纽甘,因此我們判定未知電影是愛情片
流程
實操case
pandas實現(xiàn)KNN分類器
import numpy as np
import pandas as pd
#讀取訓練樣本集數(shù)據(jù)
train = pd.read_csv()
#設置columns name
train.columns = []
#設置參數(shù)k
k = 3
#讀取測試集
test = pd.read_csv()
test.columns = []
#分類器函數(shù)
def classify(inX, dataset, labels, k):
#計算歐式距離
normMat, ranges, minVals = norm(dataset)
diffMat = pd.DataFrame((inX.values-minVals)/ranges -normMat.values, columns=dataset.columns)
sqDiffMat = diffMat**2
sqlDistances = sqDiffMat.sum(axis=1)
distances = sqlDistances**0.5
#排序取前k位
sortedDistIndices = distances.argsort()
#按頻次返回最高頻label
k_label = labels.iloc[sortedDistIndices[:k]]
label_sort = k_label.apply(pd.value_counts)
res_label = label_sort.index[0]
return res_label
#歸一化處理
#歐式計算會向大值數(shù)據(jù)傾斜,因此要做歸一處理
def norm(dataset):
t = pd.DataFrame(dataset.min())
t_min = pd.DataFrame(t.T, columns=t.index)
t = pd.DataFrame(dataset.max())
t_max = pd.DataFrame(t.T, columns=t.index)
ranges = t_max.values - t_min.values
normMat = pd.DataFrame((dataset.values - t_min.values)/ranges, columns=dataset.columns)
return normMat, ranges, t_min.values
classify(test, train[['特征']], train[['分類標簽']], k)
測試:
x = float(input('frequent flier miles earned per year?'))
y = float(input('percentage of time spent playing video games?'))
z = float(input('liters of ice cream consumed per year?'))
Inx = pd.DataFrame({'每年獲得的飛行吵槁担客里程數(shù)':'x, 玩視頻游戲所耗時間百分比':y, '每周所消費的冰淇淋公升數(shù)':z}, index=[0])
classify(Inx, train.iloc[:, :-1], train.iloc[:,-1:], 3)
這里可以使用np.seterr(divide='ignore', invalid='ignore')悍赢,去掉"divide by zero" or "divide by NaN" runtime warning, 但是強烈不建議。。左权。應該有更好的方式判斷分母是否為0或空
pyechars可視化
#散點圖可視化
def scatter_show(dataset, x_name, y_name) -> Scatter:
c = (Scatter()\
.add_xaxis(dataset[x_name])\
.add_yaxis('',
[list(z) for z in zip(dataset[y_name],
dataset['樣本分類'])],
label_opts=opts.LabelOpts(is_show=False))\
.set_global_opts(title_opts=opts.TitleOpts(title="約會網(wǎng)站配對效果-散點圖"),\
yaxis_opts=opts.AxisOpts(\
name=y_name, name_location="middle",name_rotate=90, name_gap=70),\
xaxis_opts=opts.AxisOpts(\
name=x_name,name_location="middle", name_gap=30),\
# yaxis_opts=opts.AxisOpts(boundary_gap=['20%',True],is_scale='False'),\
# xaxis_opts=opts.AxisOpts(boundary_gap=['20%',True]),\
# tooltip_opts=opts.TooltipOpts(formatter=\
# utils.JsCode("function(params) {return params.name + ' : ' + params.value[2];}")),\
visualmap_opts=opts.VisualMapOpts(type_="color",
max_=3,
min_=0,
dimension=2,
is_piecewise=True,\
pieces=[{"value": 1, "label": '不喜歡', "color": '#c7b8a1'},\
{"value": 2, "label": '魅力一般', "color": '#7b8b6f'},\
{"value": 3, "label": '極具魅力', "color": '#965454'}],\
pos_left='center', pos_top='6%', orient='horizontal')))
return c
測試:
- 每年贏得的飛行称ず客里程數(shù)與玩視頻游戲所占百分比的約會數(shù)據(jù)散點圖
scatter_show(train, '玩視頻游戲所耗時間百分比', '每年獲得的飛行常客里程數(shù)').render_notebook()
- 每周所消費的冰淇淋公升數(shù)與玩視頻游戲所占百分比的約會數(shù)據(jù)散點圖
scatter_show(train, '玩視頻游戲所耗時間百分比', '每年獲得的飛行充套埽客里程數(shù)').render_notebook()