機器學習實戰1-1 KNN電影分類遇到的問題


為什么電腦排版效果和手機排版效果不一樣~

目前只學習了python的基礎語法,有些東西理解的不透徹,希望能一邊看《機器學習實戰》,一邊加深對python的理解,所以寫的內容很淺顯,也許還會有一部分錯誤,希望得到大家的指正。在看到書上第一個KNN算法,實現簡單的電影分類的時候,就遇到了很多問題,在這里把解決方法總結下來,時常翻看,加深理解。最近時間比較充裕,希望每天都能在這里總結輸出,逐漸提升自己的能力!這樣總有一天,我能盡情的吃牛肉干不心疼錢,嗯!

我用的是python3,《機器學習實戰》里面是python2,所以有一些部分語法還是有些不同

 跟着書敲的代碼,然后自己加入了一部分注釋,代碼前面的有些注釋寫的不詳細,后面會根據我自己的理解進一步解釋

 1 #准備,用python 導入數據
 2 
 3 #導入numpy 方便矩陣操作
 4 from numpy import *
 5 #導入運算符模塊
 6 import operator  7 
 8 def createDataSet():  9     group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])#注意,這里中括號的個數 10     labels = ['A','A','B','B'] 11     return group,labels 12 
13 
14 #classify0有四個輸入變量,用於分類的輸入向量是inX,輸入的樣本集是dataSet
15 #標簽向量為labels,k是用於選擇最近的鄰居數目
16 def classify0(inX,dataSet,labels,k): 17     dataSetSize = dataSet.shape[0] #表明dataSet有幾組數據,根據上文中的group得知,應該有4組數據
18 
19     #tile是把輸入向量inX擴充成和dataSet一樣的行維度,也就是dataSet是幾個數據,就把inX擴充成幾個數據
20     #方便后面向量操作,使inX減去dataSet里的數據,這樣就可以不用循環了,直接矩陣運算就可以了
21     #計算被測點到dataSet的距離
22     diffMat = tile(inX,(dataSetSize,1)) - dataSet 

23 sqDiffMat = diffMat ** 2 24 sqDistances = sqDiffMat.sum(axis = 1) #后面詳細解釋sqDiffMat.sum(axis = 1)用法 25 distances = sqDistances ** 0.5 26 27 #對距離進行排序.numpy中的argsort()是對數組從小到大拍訊,返回值是數值對應的索引值 28 sortedDistIndicies = distances.argsort() 29 30 classCount = {}#{}表示生成的是字典,這是一個dict,用於存儲不同標簽出現的次數 31 for i in range(k): #range(k)就是range(0:k) 32 ''' 33 選取前k個距離最近的點,sortedDistIndicies是已經排序好的,用labels迭代的取前k個距離最近的樣本點的標簽 34 並計算該標簽出現的次數,這里用到了dict.get(key,default=None)函數,key就是voteIlabel,如果不存在,就返回一個0並存入dict 35 如果存在,則讀取當前值並+1 36 ''' 37 voteIlabel = labels[sortedDistIndicies[i]]#注意這里也是中括號,不是小括號 38 classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #具體怎么實現的還是不清楚,已經解決了,具體用法在有道雲筆記里,這篇文章后面也有解釋說明 39 40 ''' 41 items方法把字典中的key和value組成一個元組,並把這些元組放在列表中返回 42 operator.itemgetter(1),按照第二個元素的次序對元組進行排序,這里面第二個元素具體指的就是,標簽出現的次數 43 False是默認升序排列,True是降序排列 44 ''' 45 sortedClassCount = sorted(classCount.items(),key = operator.itemgetter(1),reverse = True) 46 return sortedClassCount[0][0] #返回頻率最高的元素標簽。這里因為是降序排列,所以第一個([0][0])就是頻率最高的那個

1、問題描述: 在python交互開發環境中,輸入

import kNN

結果返回是,no module named kNN

這個問題折磨死我了,試過添加路徑,試過好多別的方法,都不行,簡直要懷疑人生了。

解決方法:https://blog.csdn.net/lingan_hong/article/details/69526154

R&S公司用的電腦一直不行,最后解決方法是:重新安裝一遍python3.6,安裝目錄不是廖雪峰里面的默認目錄,原因是,公司電腦的默認目錄下,安裝在C盤的APPdata里面,這個文件在電腦中是隱藏的,我寫的python程序在另外的文件夾里,我想,這可能是找不到KNN這個模塊的一個可能原因之一。

再一次重新安裝的時候,我要在哪里存放腳本,就安裝在哪里。新建文件夾命名為PYTHON,將python安裝在PYTHON里,並且全選了所有要下載的東西進行安裝,安裝時間比較長。安裝之后,在cmd安裝wheel,先進入安裝python3.6的路徑,然后執行的命令是,pip install wheel 。在python安裝目錄下有一個Scrip的文件夾,我把秦大虎發給我和這個版本配套的numpy,matplolit等安裝包下載到這里,並且在cmd里進入這個安裝目錄,在執行命令 “pip install 要安裝的文件名”

 

2、問題描述:第22行,tile(inX,(dataSetSize,1)) 是什么意思 

     解決方法:tile(A,n)作用是將數組 A 重復 n 次,形成一個新的數組。

  例如,A = 1,2,3

       4,5,6

也就是說,A 是一個2行3列的矩陣,那么,B = tile [A,3],就是把A整體橫着復制3次,所以

  C = [A,(2,1)],就是把 A 看成整體,形成2行1列的數組,也就是變成:

  

 

3、問題描述:numpy sum求和中axis問題

這個問題起源於,在使用numpy中的sum語句時,語法是這樣的:

假設,a 是一個2維數組,那么為什么 a.sum(axis = 1),是對 a 的行求和,保留列數;a.sum(axis = 0),是對 a 的列求和,保留行數。但是,當a這個數組變化之后,不是2維數組,就不是按照上面規則求和了,有時甚至是甚至相同的語句下,結果是反過來的。這讓我比較困惑,這個語句究竟是怎么工作的?究竟什么時候是行相加,什么時候是列相加?為什么 a.sum(axis= 2)會報錯?為什么axis不能等於2?

解決方法:

  首先理解什么是array的維度

numpy.array的維度問題,我的理解就是能用幾個數確定array里面元素的位置,那么就是幾維。

圖1顯示了一個數組 a

 

                        圖1

其中,如圖2所示,第一維(紅色部分)有兩個(也就是長度length為2),第二維(綠色部分)有2行(長度,length = 2),第三維(粉色部分)有3列(length = 3),所以,shape(a)是(2,2,3)。注意,shape中的數字指的是長度,所以從1開始計數。索引,是指位置,從0開始計數。

                             圖2

在進一步理解一下,索引一下 a[0,1,2] ,想一想,應該是這個數組中的幾?

揭曉一下答案:

解釋:

0:指的是第一維中的第1個紅色部分的內容(索引從0開始計數),縮小了索引范圍

1:指的是第二維中的第2個綠色部分的內容,進一步縮小索引范圍

2:指的是第三維中的第3個粉色部分的內容,確定了我們要索引的數字,他就是5

由此想要知道 5 這個元素在數組中的位置,就至少需要3個數字,所以這個矩陣是一個三維數組(array)

 

   那么axis=0,axis=1,又是什么意思呢?為什么有時axis=2成立,有時axis=2不成立,會報錯?

在這里,我理解的 axis = 0 ;axis = 1; axis = 2;分別類比於3維空間里的x軸,y軸,z軸。我猜想,這也是 axis 這個單詞翻譯成軸的原因。這里的 axis=0 是指第一個維度,axis = 1是指第二個維度,axis = 3 是指第三個維度。那么在 kNN 算法實現的過程中,group長成下面這個樣子:

你看,group的數組,是幾維?

因為,group里面的元素可以用兩個數字來進行精准定位,所以,他是一個2維數組。那么此時,只有 axis = 0 和 axis = 1 這兩種情況,自然是不可能有 axis = 2 這種情況的。如果此時運行shape(group),結果應該是 (4,2)。來不信,給你運行一遍看看:

 shape(group)結果是(4,2)原因是,axis = 0 (也就是第一維)長度為4,axis = 1(也就是第二維)長度為2。

 

再舉一個栗子:

看到上面數組 a 沒有?就是下面這個

也就是說,數組 a 是一個3維數組,那么,此時你來想一想,axis = 0(也就是第一維)長度是幾?axis = 1(第二維)長度是幾?axis = 2(第三維)長度是幾?那么,也就能知道shape(a)的結果是(2,2,3)啦!

所以,我就把 axis = 0,類比想象成 x 軸;把 axis = 1 ,類比想象成 y 軸;把 axis = 2 類比想象成 z 軸。那么,再次申明一下,如果一個數組是二維的,就不可能有 axis = 2 這種情況了。

 

那么,sum(axis=0)的計算過程是怎樣的?

我們先以group.sum(axis = 1) 例,看看,結果是什么?

由結果推原因,我們可以得到,這是在把 group 的第一列和第二列相加的結果。

 

詳細的計算過程是:

當 axis = 1 時,就是是把 shape(group)的結果(4,2)中的第二維(列)相加去掉,只剩下行,也就是只剩下 axis = 0 (第一維,行)。按照我們正常的想法應該是剩下一個列向量:

[ 2.1

2

0

0.1]

但是,注意,我們一開始定義group的時候的寫法:

group = array([ [1,1.1], [1,1], [0,0], [0,0.1] ])

那么按列相加就是:

因此,在 python shell 環境中顯示出來就是行向量的形式:[2.1,2,0,0.1]

summarizegroup.sum(axis = 1)計算結果是,把axis = 1 弄消失,只剩下 axis =0 這一維度的長度保持不變。

 

再看看 group.sum(axis = 0) 結果應該是什么?

把 axis = 0 (第一維也就是行)相加去掉,只留下2列。想一下結果是什么?

結果,應該是 [2, 2.2]。

 

那么當數組 a 是三維的,a.sum(axis = 0),該怎么計算呢?

 

計算 a.sum(axis = 0) 就是把第一維相加並去掉,也就是說,把紅色部分合並相加,只剩下一個紅色的部分,那我的猜想就是,這里是不是也可以理解為把三維數組降為,變成二維呢?不知道這么相對不對啊

shape(a)結果是(2,2,3)

那么,去掉 axis = 0 就是去掉shape里的第一維:2。也就是說,最后結果的數組的shape是(2,3),即,最后是兩行三列的數組。那么想家的方法,是把下面紅色部分的數對應加到上面紅色部分的數里,所以結果就是:

[ 3,5,7

6,6,9]

     

 

4、問題描述:搞不清楚 classCount.get(voteIlabel,0)  是什么意思

     解決方法:

     上面寫了 dict.get 的用法,小白如我,還不太明白,看了好多博客,終於有了一點頭緒。

現在舉一個例子,直觀的感受一下,如果要取出dict里面的鍵值,有兩種做法。

第一種方法:不用函數,直接取出(如下圖)。注意,這種取出的方法是中括號里面加引號,內容是關鍵字,返回的是value

 

 

第二種方法:用get()函數,上面查看get的幫助,可以這樣理解,輸入的命令格式是

D.get(k[,d])

其中,D是程序中的字典,k是D中的關鍵字key,中括號里面的內容是默認參數。現在看紅色框部分是什么意思。D[k],前面已經知道,它的意思是取出 k 對應的 value。再加上 if k in D,意思就是,如果這個關鍵字 k 在字典 D 里面,那么就執行D[k],取出 k 對應的 value,如果 k 不在字典 D 里面,返回值就是 d,紅框后面告訴我們了,d 的默認值是 None。

繞來繞去的,可能會有一點暈,我們直接看例子,然后再返回頭理解上面的話

 

如果 C 不在 D 里,就返回None,在上面的例子中,我們看到,啥也沒返回,難道這就是返回None的意思?

 

之后,我改變了 d 的默認值,讓他不是None,是 0,看一下運行結果

 

意思是,C 不在 D 里,執行 D.get('C',0),返回值就是 0

 

 

 

總結:python3的語法理解不深刻,體會的不到位,需要不斷思考,不斷總結。為了可以隨心所欲的吃牛肉干,加油!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM