最近開始學習《機器學習實戰》這本書,以下是在學習過程中學到的一些python基礎知識以及算法思想。
python版本:3.6
1、算法核心思想概述
算法思想:k-近鄰算法采用測量不同特征值之間的距離方法進行分類。
優點:精度高、對異常值不敏感、無數據輸入假定
缺點:計算復雜度高、空間復雜度高
適用數據范圍:數值型、標稱型
一個樣本在特征空間里k個距離最短的樣本中,大多數樣本屬于A類,則這個樣本也屬于A類。
1.1 k-近鄰算法的一般流程
(1)收集數據:可以使用任何方法
(2)準備數據:距離計算所需的數值,最好是結構化的數據格式
(3)分析數據:可以使用任何方法
(4)測試數據:計算錯誤率
(5)使用算法:首先需要輸入樣本數據和結構化的輸出結果,然后運行kNN算法判定輸入數據屬于哪個分類,最后應用對計算出的分類執行后續的處理。
1.2 分類函數
本函數的功能為:使用kNN算法將每組數據劃分到某個類別中。首先計算出特征向量間的距離,然后選取與當前距離最小的k個點,并通過這k個點類別出現的頻率來確定當前點的預測分類。
在最初的學習中遇到以下幾個python相關的基礎知識:
(1)shape
函數
a.shape[0]
計算行數
a.shape[1]
計算列數
(2)title
函數
>>>a = array([1,2])
>>>title(a, (3,2))
array([[1, 2, 1, 2],
[1, 2, 1, 2],
[1, 2, 1, 2]])
(3)axis=0
矩陣每一列相加, axis=1
矩陣每一行相加
(4)argsort
函數:返回數組的索引值
(5)dict.get(key, default=None)
key:要查找的鍵;default:指定鍵的值不存在則返回默認值。
以下是算法詳細代碼:
from numpy import *
import operator
def createDataSet():
group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])
labels = ['A', 'A', 'B', 'B']
return group, labels
def classify0(inK, dataSet, labels, k):
# 計算訓練樣本的行數,也就是有幾組訓練樣本
dataSetSize = dataSet.shape[0]
# 將新樣本與每一個訓練樣本相減
diffMat = tile(inK, (dataSetSize, 1)) - dataSet
sqDiffMat = diffMat ** 2
# 將結果每一行相加,平方和
sqDistances = sqDiffMat.sum(axis=1)
# 求距離
distances = sqDistances ** 0.5
# 將距離按照從小到大順序排列
sortedDistIndicies = distances.argsort() # argsort返回的是索引值
classCount = {}
# 選取與當前點距離最小的K個點,確定前K個點所在類別的出現頻率
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
# 將前K個值按照出現頻率最高的類別進行逆序排序
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
執行代碼如下
import kNN
input = [3, 0]
group, labels = kNN.createDataSet()
output = kNN.classify0(input, group, labels, 3)
print("分類結果為:", output)
2、改進約會網站配對效果
示例內容:產生簡單的命令行程序,用戶可以輸入一些特征數據來判斷對方是否為自己喜歡的類型。
2.1準備數據:從文本文件中解析數據
此時數據已經存放在文本文件中,在將數據輸入到分類器之前,需要將待處理的數據變成分類器可以接受的格式。(數據為看數據所占時間數、每年的飛行里程數、每周消耗的冰淇淋公升數)
創建一個file2matrix
的函數,用來解析數據。函數的輸入為文件名稱字符,輸出為訓練樣本矩陣和類標簽向量。
以下是學到的一些小知識:
(1)readlines()
函數
使用方法:fileObject.readlines( );
返回值:返回列表,包含所有的行
(2)numpy
高維數組操作
本部分主要是想提一下以slice的方式來獲取數據
下圖來自博客園
以下是算法詳細代碼:
def file2matrix(filename):
# 得到文件的行數
fr = open(filename)
arrayOLines = fr.readlines()
numberOfLines = len(arrayOLines)
# 創建返回的numpy矩陣,矩陣使用0填充,numberOfLines行,3列
returnMat = zeros((numberOfLines, 3))
classLabelVector = []
index = 0
# 解析文件數據到列表,循環處理文件中的每行數據
for line in arrayOLines:
# 去掉每行回車字符
line = line.strip()
# 將上一步得到的整行數據分割成一個元素列表
listFromLine = line.split('\t')
# 選取列表的前3個元素并存儲到特征向量中
returnMat[index, :] = listFromLine[0:3]
# 將列表的最后一列存儲到向量中
classLabelVector.append(int(listFromLine[-1]))
index += 1
return returnMat, classLabelVector
在測試結果時,需要重載kNN模塊,需要導入模塊importlib
然后輸入如下命令:
importlib.reload(kNN)
datingDataMat, datingLabels = kNN.file2matrix('datingTestSet2.txt')
2.2分析數據:使用Matplotlib創建散點圖
本部分主要采用直觀的圖表來分析數據結構。
以下是算法詳細代碼:
import kNN
import numpy
import matplotlib
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,0], datingDataMat[:,1], 15.0*numpy.array(datingLabels), 15.0*numpy.array(datingLabels))
plt.show()
2.3準備數據:歸一化數值
由于kNN算法就是在求方差,數值偏大的屬性值的影響遠遠大于數值偏小的屬性值。故需要將數據進行歸一化處理,通常將取值范圍處理為0到1或-1到1之間。
以下是算法詳細代碼
def autoNorm(dataSet):
# 參數0指取列的最值
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
ranges = maxVals - minVals
normDataSet = zeros(shape(dataSet))
m = dataSet.shape[0]
normDataSet = dataSet - tile(minVals, (m, 1))
normDataSet = normDataSet / tile(ranges, (m, 1))
return normDataSet, ranges, minVals
2.4測試算法:作為完整程序驗證分類器
機器學習一個非常重要的工作就是評估算法的正確率,通常使用已有數據的90%作為訓練樣本來訓練分類器,剩余10%的數據用于測試分類器。可以使用錯誤率來檢測分類器的性能。對于分類器而言,錯誤率就是分類器給出錯誤結果的次數除以測試數據的總數。
算法過程
此算法首先使用file2matrix
和autoNorm
函數從文件讀取數據并將數據歸一化處理。接著確定哪些數據用于測試,哪些數據用做訓練樣本,然后將這兩部分數據輸入到分類器函數classify0
,最后輸出錯誤率。
以下是算法詳細代碼
def datingClassTest() -> object:
# 選取多少數據測試分類器
hoRatio = 0.10
# 得到數據矩陣和標簽向量
datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
# 歸一化處理矩陣
normMat, ranges, minVals = autoNorm(datingDataMat)
# 獲取矩陣的行數
m = normMat.shape[0]
# 設置測試個數(10%)
numTestVecs = int(m * hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
#第一個參數:前10%的數據用于inX;第二個參數:后90%用戶dataSet;第三個參數:后90%的數據的標簽;k=3
classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3)
print("分類后的結果為:,", classifierResult, "原結果為:", datingLabels[i])
if (classifierResult != datingLabels[i]):
errorCount += 1.0
print("錯誤率是:", (errorCount / float(numTestVecs)))
2.5使用算法:構建完整可用系統
現在通過輸入看數據所占時間數、每年的飛行里程數、每周消耗的冰淇淋公升數這些數據來給出喜歡對方程度的預測值。
以下是算法詳細代碼
def classifyPerson():
resultList = ['一點也不喜歡', '有一點喜歡', '非常喜歡']
percentTats = float(input("看視頻所占的時間比:"))
miles = float(input("每年的飛行里程數:"))
iceCream = float(input("每周消耗的冰淇淋公升數:"))
datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
normMat, ranges, minVals = autoNorm(datingDataMat)
inArr = array([miles, percentTats, iceCream])
classifierResult = classify0((inArr - minVals) / ranges, normMat, datingLabels, 3)
print("你對這個人的喜歡程度:", resultList[classifierResult - 1])