文章原創(chuàng),最近更新:2018-08-9
本章節(jié)的主要內容是:
重點介紹項目案例1: 優(yōu)化約會網(wǎng)站的配對效果中的分析數(shù)據(jù):使用 Matplotlib 畫二維散點圖。
1.KNN項目案例介紹:
項目案例1:
優(yōu)化約會網(wǎng)站的配對效果
項目概述:
1)海倫使用約會網(wǎng)站尋找約會對象。經(jīng)過一段時間之后,她發(fā)現(xiàn)曾交往過三種類型的人: 不喜歡的人、魅力一般的人、 極具魅力的人。
2)她希望: 1. 工作日與魅力一般的人約會 2. 周末與極具魅力的人約會 3. 不喜歡的人則直接排除掉?,F(xiàn)在她收集到了一些約會網(wǎng)站未曾記錄的數(shù)據(jù)信息,這更有助于匹配對象的歸類。
開發(fā)流程:
- 收集數(shù)據(jù):提供文本文件
- 準備數(shù)據(jù):使用 Python 解析文本文件
- 分析數(shù)據(jù):使用 Matplotlib 畫二維散點圖
- 訓練算法:此步驟不適用于 k-近鄰算法
- 測試算法:使用海倫提供的部分數(shù)據(jù)作為測試樣本。
測試樣本和非測試樣本的區(qū)別在于:測試樣本是已經(jīng)完成分類的數(shù)據(jù),如果預測分類與實際類別不同,則標記為一個錯誤。 - 使用算法:產(chǎn)生簡單的命令行程序,然后海倫可以輸入一些特征數(shù)據(jù)以判斷對方是否為自己喜歡的類型。
數(shù)據(jù)集介紹
海倫把這些約會對象的數(shù)據(jù)存放在文本文件 datingTestSet2.txt (數(shù)據(jù)來源于《機器學習實戰(zhàn)》第二章 k鄰近算法)中,總共有 1000 行。
本文使用的數(shù)據(jù)主要包含以下三種特征:每年獲得的飛行??屠锍虜?shù),玩視頻游戲所耗時間百分比,每周消費的冰淇淋公升數(shù)。其中分類結果作為文件的第四列,并且只有3、2、1三種分類值。datingTestSet2.csv文件格式如下所示:
| 飛行里程數(shù) | 游戲耗時百分比 | 冰淇淋公升數(shù) | 分類結果 |
|---|---|---|---|
| 40920 | 8.326976 | 0.953952 | 3 |
| 14488 | 7.153469 | 1.673904 | 2 |
| 26052 | 1.441871 | 0.805124 | 1 |
數(shù)據(jù)在datingTestSet2.txt文件中的格式如下所示:

2.使用 Matplotlib 畫二維散點圖
使用Matplotlib創(chuàng)建散點圖,相關代碼如下:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*np.array(datingLabels),15.0*np.array(datingLabels))
plt.show()
輸出結果如下:

上圖利用datingLabels存儲的類標簽屬性,在散點圖上繪制了色彩不等、尺寸不同的點。因而基本上可以從圖中看到數(shù)據(jù)點所屬三個樣本分類的區(qū)域輪廓。為了得到更好的效果,采用datingDataMat矩陣的屬性列1和2展示數(shù)據(jù),并以紅色的'*'表示類標簽1、藍色的'o'表示表示類標簽2、綠色的'+'表示類標簽3,修改參數(shù)如下:
import kNN
import operator
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
group,labels=kNN.createDataSet()
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
#ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*np.array(datingLabels),15.0*np.array(datingLabels))
datingLabels = np.array(datingLabels)
idx_1 = np.where(datingLabels==1)
p1 = ax.scatter(datingDataMat[idx_1,0],datingDataMat[idx_1,1],marker = '*',color = 'r',label='1',s=10)
idx_2 = np.where(datingLabels==2)
p2 = ax.scatter(datingDataMat[idx_2,0],datingDataMat[idx_2,1],marker = 'o',color ='g',label='2',s=20)
idx_3 = np.where(datingLabels==3)
p3 = ax.scatter(datingDataMat[idx_3,0],datingDataMat[idx_3,1],marker = '+',color ='b',label='3',s=30)
plt.xlabel("每年獲取的飛行里程數(shù)",fontproperties=font)
plt.ylabel("玩視頻游戲所消耗的事件百分比",fontproperties=font)
ax.legend((p1,p2,p3),("不喜歡","魅力一般","極具魅力"),loc=2,prop=font)
plt.show()
輸出結果如下:

3.相關知識點
知識點1:plt.figure()
figure概念的理解,具體如下圖:
我們先理清 figure的概念。用畫板和畫紙來做比喻的話,figure就好像是畫板,是畫紙的載體,但具體畫畫等操作是在畫紙上完成的。在pyplot中,畫紙的概念對應的就是Axes/Subplot。

figure語法說明,具體如下:
figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None, frameon=True)
- num:圖像編號或名稱,數(shù)字為編號 ,字符串為名稱
- figsize:指定figure的寬和高,單位為英寸;
- dpi參數(shù)指定繪圖對象的分辨率,即每英寸多少個像素,缺省值為80
- facecolor:背景顏色
- edgecolor:邊框顏色
- frameon:是否顯示邊框
具體小案例如下:
案例1
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(4,3),facecolor="blue")
plt.subplot(221)
plt.show()
輸出結果如下:

案例2
import matplotlib.pyplot as plt
fig = plt.figure(facecolor="blue")
plt.subplot(221)
plt.show()
輸出結果如下:

知識點2:畫子圖add_subplot新增子圖
首先要理解一些概念問題,具體如下:
- 子圖:就是在一張figure里面生成多張子圖。
- Matplotlib對象簡介
- FigureCanvas:畫布
- Figure:圖
- Axes:坐標軸(實際畫圖的地方)
add_subplot的參數(shù)與subplots的相似
subplot語法,具體如下:
subplot(nrows,ncols,sharex,sharey,subplot_kw,**fig_kw)

備注:subplot可以規(guī)劃figure劃分為n個子圖,但每條subplot命令只會創(chuàng)建一個子圖 。學習參考鏈接如下:matplotlib命令與格式:圖像(figure)與子區(qū)域(axes)布局與規(guī)劃
案例1:add_subplot()
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 100)
fig = plt.figure()
ax1 = fig.add_subplot(221)
ax1.plot(x, x)
ax2 = fig.add_subplot(222)
ax2.plot(x, -x)
ax3 = fig.add_subplot(223)
ax3.plot(x, x ** 2)
ax4 = fig.add_subplot(224)
ax4.plot(x, np.log(x))
plt.show()
輸出結果:

案例2:subplot()
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 100)
plt.subplot(221)
plt.plot(x, x)
plt.subplot(222)
plt.plot(x, -x)
plt.subplot(223)
plt.plot(x, x ** 2)
plt.subplot(224)
plt.plot(x, np.log(x))
plt.show()
輸出結果如下:

add_subplot()與subplot()的區(qū)別:具體可參見python matplotlib中axes與axis的區(qū)別?
知識點3:scatter(x, y, 點的大小, 顏色,標記)
matplotlib模塊中scatter函數(shù)語法及參數(shù)含義:
plt.scatter(x, y, s=20,
c=None, marker='o',
cmap=None, norm=None,
vmin=None, vmax=None,
alpha=None, linewidths=None,
edgecolors=None)
- x:指定散點圖的x軸數(shù)據(jù);
- y:指定散點圖的y軸數(shù)據(jù);
- s:指定散點圖點的大小,默認為20,通過傳入新的變量,實現(xiàn)氣泡圖的繪制;
- c:指定散點圖點的顏色,默認為藍色;
- marker:指定散點圖點的形狀,默認為圓形;
- cmap:指定色圖,只有當c參數(shù)是一個浮點型的數(shù)組的時候才起作用;
- norm:設置數(shù)據(jù)亮度,標準化到0~1之間,使用該參數(shù)仍需要c為浮點型的數(shù)組;
- vmin、vmax:亮度設置,與norm類似,如果使用了norm則該參數(shù)無效;
- alpha:設置散點的透明度;
- linewidths:設置散點邊界線的寬度;
- edgecolors:設置散點邊界線的顏色;
學習參考鏈接:# 從零開始學Python【15】--matplotlib(散點圖)
scatter(x, y, 點的大小, 顏色,標記),這是最主要的幾個用法,如果括號中不寫s= c=則按默認順序,寫了則按規(guī)定的來,不考慮順序.
案例1
具體小案例如下:
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter([1,2,3,4],[2,4,6,8],[10,20,30,40],['r', 'b','y','k']) #x,y,大小,顏色,顏色也可以用隨意的數(shù)字代替,比如[1,2,3,4]表示不同顏色即可,具體怎么設置想要的顏色后續(xù)再研究
plt.show()
輸出結果如下:

案例2
根據(jù)文中的源代碼案例,具體如下:
- scatter(x, y)
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*np.array(datingLabels),1
顯示的結果如下:

總結:
點的大小一樣,未采用色彩或其他的記號來標記不同樣本分類,不能很好地理解數(shù)據(jù)信息.
- scatter(x, y, 點的大小)
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*np.array(datingLabels))

總結:
點的大小不一樣,未采用色彩或其他的記號來標記不同樣本分類,不能很好地理解數(shù)據(jù)信息.
- scatter(x, y, 點的大小, 顏色)
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*np.array(datingLabels),15.0*np.array(datingLabels)) #參數(shù)分別代表x,y
輸出結果如下:

點的大小不一樣,采用色彩或其他的記號來標記不同樣本分類,能很好地理解數(shù)據(jù)信息.
知識點4:plt.xlabel()與plt.ylabel()
xlabel、ylabel:分別設置X、Y軸的標題文字。
知識點5:legend()
legend:顯示圖示,即圖中表示每條曲線的標簽(label)和樣式的矩形區(qū)域。
參考鏈接:matplotlib命令與格式:圖例legend語法及設置
legend語法參數(shù)如下: matplotlib.pyplot.legend(*args, **kwargs)
- loc:圖例所有figure位置
plt.legend(loc='lower left')

- prop:字體參數(shù)
知識點6:np.where()
numpy.where(condition[, x, y])
- 這里x,y是可選參數(shù),condition是條件,這三個輸入?yún)?shù)都是array_like的形式;而且三者的維度相同
- 當conditon的某個位置的為true時,輸出x的對應位置的元素,否則選擇y對應位置的元素;
- 如果只有參數(shù)condition,則函數(shù)返回為true的元素的坐標位置信息;
學習參考鏈接:怎么理解numpy的where()?
而本章的源代碼就是第二種情況,具體小案例如下:
np.where(x)輸出的是九個不為0的數(shù)(為真的數(shù)的坐標,第一個array[]是橫坐標,第二個array[]是縱坐標.
x=np.array([[9,1,2],[3,4,5],[6,7,8]])
x
Out[85]:
array([[9, 1, 2],
[3, 4, 5],
[6, 7, 8]])
np.where(x)
Out[86]:
(array([0, 0, 0, 1, 1, 1, 2, 2, 2], dtype=int64),
array([0, 1, 2, 0, 1, 2, 0, 1, 2], dtype=int64))

x=np.array([[9,1,2],[3,4,5],[6,7,8]])
x[np.where(x)]
Out[88]: array([9, 1, 2, 3, 4, 5, 6, 7, 8])
知識點7:Matplotlib支持中文的方法
Matplotlib默認不支持中文,需要在在python腳本的開頭加上下面的代碼:
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
上面從matplotlib.font_manager字體管理模塊代入FontProperties,然后設置字體屬性,FontProperties()設置的是Windows系統(tǒng)自帶的宋體。關于Windows字體列表,可以查閱WIKI Windows字體列表,size設置的是字體的大小。