機器學習小記——KNN(K近鄰) ^_^ (一)

爲了讓絕大多數人均可以看懂,因此我就用簡單的話語來說解機器學習每個算法php

第一次寫ML的博文,因此可能會有些地方出錯,歡迎各位大佬提出意見或錯誤python

祝你們開心進步每一天~算法

博文代碼所有爲python機器學習

 

簡單的說一下什麼是機器學習,機器學習英文名稱是Machine Learning, MLide

機器學習(Machine Learning, ML)是一門多領域交叉學科,涉及機率論、統計學、逼近論、凸分析、算法複雜度理論等多門學科。專門研究計算機怎樣模擬或實現人類的學習行爲,以獲取新的知識或技能,從新組織已有的知識結構使之不斷改善自身的性能。

機器學習學習形式可分爲監督學習,監督學習,半監督學習和強化學習

KNN(k-Nearest Neighbor)中文名爲K近鄰,是分類算法的一種,KNN的思路爲在在數據和標籤已知的狀況下將測試數據的特徵和訓練集中的特徵進行比較,找到與之最類似的k的數據,那麼這個數據對應的類別就是k個數據中出現次數最多的那個類別函數

尋找類似度有多重方法,最經常使用的爲歐幾里得度量皮爾遜相關係數餘弦類似度性能

算法流程大體分爲 學習

  1)計算測試數據與各個訓練數據之間的距離;

  2)按照距離的遞增關係進行排序;

  3)選取距離最小的K個點;

  4)肯定前K個點所在類別的出現頻率;

  5)返回前K個點中出現頻率最高的類別做爲測試數據的預測分類。

 

本文使用iris數據集,可從UCI處下載    傳送門測試

使用py的三種庫pandas,numpy,sklearnidea

查看數據集

 

前4列爲特徵,最後一列爲標籤

1 #獲取數據
2 X=np.loadtxt("/Users/galan/py/ML-D/iris.data.txt",delimiter=",",dtype=float,usecols=(0,1,2,3))
3 y=np.loadtxt("/Users/galan/py/ML-D/iris.data.txt",delimiter=",",dtype=str,usecols=(4,))
4 #建立訓練數據和測試數據
5 X_train,X_test,y_train,y_test=train_test_split(X,y,train_size=.7)

第2,3行爲獲取特徵和標籤

第五行中使用sklearn庫的train_test_split函數,用來方便分隔測試集和訓練集

 

本文使用歐幾里得度量算法,在下方也會列出皮爾遜類似性和餘弦類似度的py代碼

歐幾里得度量多爲計算空間中兩點間的距離

表達式爲    |x| = √( x[1]2 + x[2]2 + … + x[n]2 )

代碼表現形式爲  [(p1-q1)**2+(p2-q2)**2+...+(pn-qn)**2]**0.5

def eculidean(p,q):
    sumSq=0.0
    #講差值德平方累加起來
    for i in range(len(p)):
        sumSq+=sum(p[i]-q[i])**2
    #求平方根
    return (sumSq**0.5)

 

皮爾遜相關係數是度量兩個變量之間相關程度,介於-1和1之間,1表明變量徹底正相關,0表明無關,-1表明徹底負關係

def pearson(x,y):
    n=len(x)
    vals=range(n)
    #簡單求和
    sumx=sum([float(x[i]) for i in vals])
    sumy=sum([float(y[i]) for i in vals])
    #求平方和
    sumxSq=sum([x[i]**2.0 for i in vals])
    sumySq=sum([y[i]**2.0 for i in vals])
    #求乘積之和
    pSum=sum([x[i]*y[i] for i in vals])
    #計算皮爾遜評價值
    num=pSum-(sumx*sumy/n)
    den=((sumxSq-pow(sumx,2)/n)*(sumySq-pow(sumy,2)/n))**.5
    if den==0:return 1
    
    r=num/den
    return r

 

餘弦類似度將向量根據座標值,繪製到向量空間中求得他們的夾角,並得出夾角對應的餘弦值,夾角越小,餘弦值越接近於1,它們的方向更加吻合,則越類似。

#vect1,vect2位兩個一維向量如(1,1)
def getCost(vect1,vect2):
    sum_x=0.0
    sum_y=0.0
    sum_xy=0.0
    for a,b in zip(vect1,vect2):
        sum_xy+=a*b
        sum_x+=a**2
        sum_y+=b**2
        if sum_x==0.0 or sum_y==0.0:
            return None
        else:
            return sum_xy/((sum_x*sum_y)**0.5)

 

knn的求證過程

#K值
k=5
#計算全部的歐氏距離組合成字典
Dists={}
for i in range(len(X_train)):
    Dists[eculidean(X_test[0],X_train[i])]=y_train[i]
#排序字典
sortedDist=sorted(Dists.iteritems(),reverse=True,key=lambda x:x[0])[:k]
classCount={}
#尋找最多的類別標籤
for i in sortedDist:
    if i[1] in classCount:
        classCount[i[1]]+=1
    else:
        classCount[i[1]]=1
print classCount

 

下面貼出全部的代碼

#coding:utf-8
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split

#獲取數據
X=np.loadtxt("./ML-D/iris.data.txt",delimiter=",",dtype=float,usecols=(0,1,2,3))
y=np.loadtxt("./ML-D/iris.data.txt",delimiter=",",dtype=str,usecols=(4,))
#建立訓練數據和測試數據
X_train,X_test,y_train,y_test=train_test_split(X,y,train_size=.7)

def eculidean(p,q):
    sumSq=0.0
    #講差值德平方累加起來
    for i in range(len(p)):
        sumSq+=sum(p-q[i])**2
    #求平方根
    return (sumSq**0.5)

def classify(X_train,X_test,k):
    #計算全部的歐氏距離
    Dists={}
    for i in range(len(X_train)):
        Dists[eculidean(X_test,X_train[i])]=y_train[i]
    #排序字典
    sortedDist=sorted(Dists.iteritems(),reverse=True,key=lambda x:x[0])[:k]
    classCount={}
    #尋找最多的類別標籤
    for i in sortedDist:
        if i[1] in classCount:
            classCount[i[1]]+=1
        else:
            classCount[i[1]]=1
    return sorted(classCount.iteritems(),key=lambda x:x[1],reverse=True)

if __name__ == '__main__':
    print "%s的類別爲%s"%(X_test[15],classify(X_train,X_test[0],5)[0][0])

 

我會每週更新一篇ML博文,方便你們學習,^_^ 共同窗習共同提升,歡迎你們前來對個人文章提出寶貴意見

祝你們週末愉快~

相關文章
相關標籤/搜索