KNN算法的個人理解

KNN算法被稱爲 lazy 算法,只有在判斷未知類別的元素時纔會建立模型進行計算。

KNN算法可以分爲以下三步:

1 存儲已知類別的元素。

2 來了一個新的元素後,計算所有已知元素與它的歐式距離。可以採用加權歐氏距離來計算。

3 取出與待分類元素最近的k個類型已知的元素,這個k個元素中大多數元素屬於哪個類別,那麼待分類元素就屬於哪個類別。


怎樣存儲?怎樣使第二步的計算量最少?


例子: 已知一些電影的類別(romance,action), 這些電影爲二維數據(打鬥次數、接吻次數)

電影名稱 打鬥次數 接吻次數 電影類型
California Man 
 
3 104 Romance
He’s Not Really into Dudes 
 
2 100 Romance
Beautiful Woman 
 
1 81 Romance
Kevin Longblade 
 
101 10 Action
Robo Slayer 3000 
 
99 5 Action
Amped II 
 
98 2 Action
未知 18 90 Unknown

現在有一個未知的電影類別,怎樣判斷它是action 還是 romance 呢?

按照上面的步驟:

1 先將已知類別的電影儲存起來。

已python語言爲例:

構建一個類,類中對象的元素有:打鬥次數,接吻次數,所屬類別(romance或action),編號(先存儲的編號爲0,然後依次增加)

在類中,有一個全局列表來存儲對象,有一個全局的迭代器來遞增對象的編號,

我們將上面6部電影的對象存儲到列表中。

2 來一個新的元素與K值,要計算它與所有對象的的距離,並取出距離最小額前K個

   函數1:計算距離 歐氏距離

     函數2:調用函數1 循環遍歷全局列表,並將每個元素與待分類元素的距離存入“距離列表”中,對“距離列表”排序。返回“距離列表”

3 判斷大多數元素的類別

    函數3:調用函數3 從“距離列表“中選出大多數元素屬於哪一個類別,然後返回次類別。

 附python代碼 按照數據挖掘學習札記:KNN算法(二)中的python代碼仿寫:

from math import sqrt

class Movie:
	"""docstring for Movie"""

	lib=[] 
	total=0 # number of movies

	def __init__(self, nk, nf, tag):
		self.nkiss = nk
		self.nfight = nf
		self.tag = tag
		self.index = len(Movie.lib)+1
		Movie.lib.append(self) # append a movie(object) to lib
		Movie.total+=1

	def distance(self,movie):
		if type(self)!=type(movie):
			raise TypeError('require type %s, give type %s'% (type(self),type(movie)))
		else:
			dis=(self.nkiss-movie.nkiss)**2
			dis+=(self.nfight-movie.nfight)**2
			dis=sqrt(dis)
	def neighbors(self,k):
		dis=[]
		movie_many=[]
		for movie in self.lib:
			dis.append((movie, self.distance(movie)))
		dis.sort(key=lambda dis:dis[1])

		for i in range(0,k+1):
			movie_many.append(dis[i][0])
		return movie_many

	def label(self,k=1):
		if self.tag == "unknown":
			movie_many = self.neighbors(k)
			nr=0
			na=0
			for movie in movie_many:
				if movie.tag == "R":
					nr+=1
				elif movie.tag == "A":
					na+=1
				else:
					raise TypeError('The movie with tag %d is not a training data'% movie.tag)
			if nr>na:
				tag="R"
			elif nr<na:
				tag="A"
			else:
				tag="known"
		return tag


if __name__ == '__main__':
    Movie(3,104,'R')
    
    Movie(2,100,'R')
    
    Movie(1,81,'R')
    Movie(101,10,'A')
    Movie(99,5,'A')
    Movie(98,2,'A')
    
    test=Movie(18,90,'unknown')
    
    print "begin test"
    
    print "test.label: " , test.label(1)




發佈了32 篇原創文章 · 獲贊 5 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章