為什么電腦排版效果和手機排版效果不一樣~
目前只學習了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]
summarize:group.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的語法理解不深刻,體會的不到位,需要不斷思考,不斷總結。為了可以隨心所欲的吃牛肉干,加油!