摘要:項目介紹某用戶一直使用在線約會軟件尋找適合自己的約會對象。盡管約會網(wǎng)站會推薦不同的人選但她并不是喜歡每一個人。
1 項目介紹
某APP用戶一直使用在線約會軟件尋找適合自己的約會對象。盡管約會網(wǎng)站會推薦不同的人選,但她并不是喜歡每一個人。經(jīng)過一番總結(jié),她發(fā)現(xiàn)曾交往過三種類型的人:
不喜歡的人(3)
魅力一般的人(2)
極具魅力的人(1)
某APP用戶希望分類軟件可以更好地幫助她將匹配對象劃分到確切的分類中。此外還可以收集了約會軟件未曾記錄的數(shù)據(jù)信息,她認(rèn)為這些數(shù)據(jù)更有助于匹配對象的歸類。收集的部分信息如下圖所示:
數(shù)據(jù)集下載
樣本主要包含以下3種特征:
每年獲得的飛行常客里程數(shù)
玩視頻游戲所耗時間百分比
每周消費(fèi)的冰淇淋公升數(shù)
2 準(zhǔn)備數(shù)據(jù):從文本文件中解析數(shù)據(jù)在將上述特征數(shù)據(jù)輸入到分類器之前,必須將待處理數(shù)據(jù)的格式改變?yōu)榉诸惼骺梢越邮艿母袷健?/p>
import numpy as np def file2matrix(filename): """ :param filename: APP用戶收集的約會數(shù)據(jù)的文件名 :return: returnMat: 用戶提供的每行數(shù)據(jù)信息,三列, 分別是每年獲得的飛行常客里程數(shù), 玩視頻游戲所耗時間百分比, 每周消費(fèi)的冰淇淋公升數(shù) classLabelVetor: 用戶的評價信息, 一般分為3類(1,2,3) """ fr = open(filename) arrayOfLines = fr.readlines() # print(arrayOfLines) # 獲得文件行數(shù); numerOfLines = len(arrayOfLines) # 創(chuàng)建要返回的Numpy矩陣; returnMat = np.zeros((numerOfLines, 3)) # 解析文件數(shù)據(jù)到矩陣中; classLabelVetor = [] index = 0 for line in arrayOfLines: line = line.strip() listFromLine = line.split(" ") returnMat[index, :] = listFromLine[0:3] classLabelVetor.append(listFromLine[-1]) index += 1 return returnMat, classLabelVetor print(file2matrix("data/datingTestSet2"))
返回的值顯示:
3 分析數(shù)據(jù):使用 Matplotlib 創(chuàng)建散點圖使用Matplotlib庫圖形化清晰地標(biāo)識了三個不同的樣本分類區(qū)域,具有不同愛好的人其類別區(qū)域也不同。
def draw_pic(datingDataMat, datingLabels): """ 每年獲取的飛行常客里程數(shù)與每周所消費(fèi)的冰淇淋公升數(shù)”構(gòu)成的散點圖。 :param datingDataMat: :param datingLabels: :return: """ # 中文顯示亂碼問題; myfont = font_manager.FontProperties(fname="/usr/share/fonts/cjkuni-uming/uming.ttc", size=12) # 創(chuàng)建畫布 fig = plt.figure() ax = fig.add_subplot(111) ax.scatter(datingDataMat[:, 0], datingDataMat[:, 2], 15 * datingLabels, datingLabels) plt.xlabel("每年的飛行里程數(shù)", fontproperties=myfont) plt.ylabel("每周消費(fèi)的冰淇淋公升數(shù)", fontproperties=myfont) plt.grid(alpha=0.5) plt.show()
效果展示
4 準(zhǔn)備數(shù)據(jù):歸一化數(shù)值計算樣本3和樣本4之間的距離:
問題:
飛行常客里程數(shù)對于計算結(jié)果的影響將遠(yuǎn)遠(yuǎn)大于其他兩個特征的影響
解決方式:
處理不同取值范圍的特征值時,通常采用的方法是將數(shù)值歸一化,如將取值范圍處理為0到1或者-1到1之間。
歸一化公式: newValue = oldValue / max
def autoNorm(dataSet): """ 歸一化數(shù)值, :param dataSet:用戶提供的每行數(shù)據(jù)信息,三列; :return: normDataSet: 歸一化的特征信息; maxVals:每個特征數(shù)據(jù)的最大值; """ # 獲取每個特征數(shù)據(jù)的最大值; maxVals = dataSet.max(0) # 獲取樣本個數(shù); m = dataSet.shape[0] # 根據(jù)公式生成歸一化的特征信息; normDataSet = dataSet / np.tile(maxVals, (m, 1)) return normDataSet, maxVals4 實施 kNN 算法
對未知類別屬性的數(shù)據(jù)集中的每個點依次執(zhí)行以下操作, 與上一個案例代碼相同:
(1) 計算已知類別數(shù)據(jù)集中的點與當(dāng)前點之間的距離;
(2) 按照距離遞增次序排序;
(3) 選取與當(dāng)前點距離最小的k個點;
(4) 確定前k個點所在類別的出現(xiàn)頻率;
(5) 返回前k個點出現(xiàn)頻率最高的類別作為當(dāng)前點的預(yù)測分類。
def classify(inX, dataSet, labels, k): """ :param inX: 要預(yù)測的數(shù)據(jù) :param dataSet: 我們要傳入的已知數(shù)據(jù)集 :param labels: 我們要傳入的標(biāo)簽 :param k: KNN里的k, 也就是說我們要選幾個近鄰 :return: 排序的結(jié)果 """ dataSetSize = dataSet.shape[0] # (6,2) 6 # tile會重復(fù)inX, 把他重復(fù)成(datasetsize, 1)型的矩陣 # print(inX) # (x1 - y1), (x2- y2) diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet # 平方 sqDiffMat = diffMat ** 2 # 相加, axis=1 行相加 sqDistance = sqDiffMat.sum(axis=1) # 開根號 distances = sqDistance ** 0.5 # print(distances) # 排序 輸出的是序列號index,并不是值 sortedDistIndicies = distances.argsort() # print(sortedDistIndicies) classCount = {} for i in range(k): voteLabel = labels[sortedDistIndicies[i]] classCount[voteLabel] = classCount.get(voteLabel, 0) + 1 # print(classCount) sortedClassCount = sorted(classCount.items(), key=lambda d: float(d[1]), reverse=True) return sortedClassCount[0]5 測試算法:作為完整程序驗證分類器
如果分類器的正確率滿足要求,就可以使用這個軟件來處理約會網(wǎng)站提供的約會名單了。機(jī)器學(xué)習(xí)算法一個很重要的工作就是評估算法的正確率,通常我們只提供已有數(shù)據(jù)的90%作為訓(xùn)練樣本來訓(xùn)練分類器,而使用其余的10%數(shù)據(jù)去測試分類器,檢測分類器的正確率。
def datingClassTest(): """ 分類器針對約會網(wǎng)站的測試代碼, 獲取錯誤率; :return: """ hoRatio = 0.10 datingDataMat, datingLabels = file2matrix("data/datingTestSet2") normDataSet, maxVals = autoNorm(datingDataMat) # 樣本個數(shù) m = normDataSet.shape[0] # 測試集個數(shù); numTestVecs = int(m*hoRatio) errorCount = 0.0 for i in range(numTestVecs): classiferResult = classify(normDataSet[i, :], normDataSet[numTestVecs:m, :], datingLabels[numTestVecs:m], 3) # print(classiferResult) if classiferResult != datingLabels[i]: errorCount += 1 print("正確結(jié)果:", datingLabels[i]) print("預(yù)測結(jié)果:", classiferResult) # print("錯誤個數(shù):", errorCount) return errorCount
執(zhí)行效果展示:
6 使用算法:構(gòu)建完整可用的預(yù)測系統(tǒng)def classifyPerson(Person): """ 使用這個分類器為某APP用戶來對人們分類。 :param Person: :return: """ datingDataMat, datingLabels = file2matrix("data/datingTestSet2") normDataSet, maxVals = autoNorm(datingDataMat) classiferResult = classify(Person / maxVals, normDataSet, datingLabels, 3) if classiferResult == "1": print("不喜歡") elif classiferResult == "2": print("有一點喜歡") else: print("非常喜歡")完整代碼
# encoding:utf-8 """ KNN實現(xiàn),基于KNN分類的約會網(wǎng)站配對改進(jìn)算法 """ import numpy as np import matplotlib.pyplot as plt from matplotlib import font_manager def file2matrix(filename): """ :param filename: APP用戶收集的約會數(shù)據(jù)的文件名 :return: returnMat: 用戶提供的每行數(shù)據(jù)信息,三列, 分別是每年獲得的飛行常客里程數(shù), 玩視頻游戲所耗時間百分比, 每周消費(fèi)的冰淇淋公升數(shù) classLabelVetor: 用戶的評價信息, 一般分為3類(1,2,3) """ fr = open(filename) arrayOfLines = fr.readlines() # print(arrayOfLines) # 獲得文件行數(shù); numerOfLines = len(arrayOfLines) # 創(chuàng)建要返回的Numpy矩陣; returnMat = np.zeros((numerOfLines, 3)) # 解析文件數(shù)據(jù)到矩陣中; classLabelVetor = [] index = 0 for line in arrayOfLines: line = line.strip() listFromLine = line.split(" ") returnMat[index, :] = listFromLine[0:3] classLabelVetor.append(listFromLine[-1]) index += 1 return returnMat, classLabelVetor def autoNorm(dataSet): """ 歸一化數(shù)值, 計算樣本3和樣本4之間的距離: [(0-67)**2 + (20000 - 32 000)**2 + (1.1 - 0.1)**2]**0.5 問題: 飛行常客里程數(shù)對于計算結(jié)果的影響將遠(yuǎn)遠(yuǎn)大于其他兩個特征的影響 解決方式: 處理不同取值范圍的特征值時, 通常采用的方法是將數(shù)值歸一化,如將取值范圍處理為0到1或者-1到1之間。 歸一化公式: newValue = oldValue / max :param dataSet:用戶提供的每行數(shù)據(jù)信息,三列; :return: normDataSet: 歸一化的特征信息; maxVals:每個特征數(shù)據(jù)的最大值; """ # 獲取每個特征數(shù)據(jù)的最大值; maxVals = dataSet.max(0) # 獲取樣本個數(shù); m = dataSet.shape[0] # 根據(jù)公式生成歸一化的特征信息; normDataSet = dataSet / np.tile(maxVals, (m, 1)) return normDataSet, maxVals def draw_pic(datingDataMat, datingLabels): """ 每年獲取的飛行常客里程數(shù)與每周所消費(fèi)的冰淇淋公升數(shù)”構(gòu)成的散點圖。 :param datingDataMat: :param datingLabels: :return: """ # 中文顯示亂碼問題; myfont = font_manager.FontProperties(fname="/usr/share/fonts/cjkuni-uming/uming.ttc", size=12) # 創(chuàng)建畫布 fig = plt.figure() ax = fig.add_subplot(111) ax.scatter(datingDataMat[:, 0], datingDataMat[:, 2], 15 * datingLabels, datingLabels) plt.xlabel("每年的飛行里程數(shù)", fontproperties=myfont) plt.ylabel("每周消費(fèi)的冰淇淋公升數(shù)", fontproperties=myfont) plt.grid(alpha=0.5) plt.show() def classify(inX, dataSet, labels, k): """ :param inX: 要預(yù)測的數(shù)據(jù) :param dataSet: 我們要傳入的已知數(shù)據(jù)集 :param labels: 我們要傳入的標(biāo)簽 :param k: KNN里的k, 也就是說我們要選幾個近鄰 :return: 排序的結(jié)果 """ dataSetSize = dataSet.shape[0] # (6,2) 6 # tile會重復(fù)inX, 把他重復(fù)成(datasetsize, 1)型的矩陣 # print(inX) # (x1 - y1), (x2- y2) diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet # 平方 sqDiffMat = diffMat ** 2 # 相加, axis=1 行相加 sqDistance = sqDiffMat.sum(axis=1) # 開根號 distances = sqDistance ** 0.5 # print(distances) # 排序 輸出的是序列號index,并不是值 sortedDistIndicies = distances.argsort() # print(sortedDistIndicies) classCount = {} for i in range(k): voteLabel = labels[sortedDistIndicies[i]] classCount[voteLabel] = classCount.get(voteLabel, 0) + 1 # print(classCount) sortedClassCount = sorted(classCount.items(), key=lambda d: float(d[1]), reverse=True) return sortedClassCount[0][0] def datingClassTest(): """ 分類器針對約會網(wǎng)站的測試代碼, 獲取錯誤率; :return: """ hoRatio = 0.10 datingDataMat, datingLabels = file2matrix("data/datingTestSet2") normDataSet, maxVals = autoNorm(datingDataMat) # 樣本個數(shù) m = normDataSet.shape[0] # 測試集個數(shù); numTestVecs = int(m*hoRatio) errorCount = 0.0 for i in range(numTestVecs): classiferResult = classify(normDataSet[i, :], normDataSet[numTestVecs:m, :], datingLabels[numTestVecs:m], 3) # print(classiferResult) if classiferResult != datingLabels[i]: errorCount += 1 print("正確結(jié)果:", datingLabels[i]) print("預(yù)測結(jié)果:", classiferResult) # print("錯誤個數(shù):", errorCount) return errorCount def classifyPerson(Person): """ 使用這個分類器為某APP用戶來對人們分類。 :param Person: :return: """ datingDataMat, datingLabels = file2matrix("data/datingTestSet2") normDataSet, maxVals = autoNorm(datingDataMat) classiferResult = classify(Person / maxVals, normDataSet, datingLabels, 3) if classiferResult == "1": print("不喜歡") elif classiferResult == "2": print("有一點喜歡") else: print("非常喜歡") if __name__ == "__main__": # personData = [30000, 10, 1.3] personData = [40920, 8.326976, 0.953952] classifyPerson(personData)
執(zhí)行結(jié)果
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/43593.html
摘要:項目介紹某用戶一直使用在線約會軟件尋找適合自己的約會對象。盡管約會網(wǎng)站會推薦不同的人選但她并不是喜歡每一個人。 1 項目介紹 某APP用戶一直使用在線約會軟件尋找適合自己的約會對象。盡管約會網(wǎng)站會推薦不同的人選,但她并不是喜歡每一個人。經(jīng)過一番總結(jié),她發(fā)現(xiàn)曾交往過三種類型的人: 不喜歡的人(3) 魅力一般的人(2) 極具魅力的人(1) 某APP用戶希望分類軟件可以更好地幫助她將匹...
摘要:鄰近算法實例額一改進(jìn)約會網(wǎng)站的配對效果應(yīng)用背景某約會網(wǎng)站收集了一些數(shù)據(jù)放在中,每個樣本數(shù)據(jù)占據(jù)一行,總共有行。在中創(chuàng)建名為的函數(shù),以此來處理輸人格式問題。該函數(shù)的輸人為文件名字符串輸出為訓(xùn)練樣本矩陣和類標(biāo)簽向量。 k鄰近算法實例額(一) 改進(jìn)約會網(wǎng)站的配對效果 應(yīng)用背景: 某約會網(wǎng)站收集了一些數(shù)據(jù)放在datingTestSet.txt中,每個樣本數(shù)據(jù)占據(jù)一行,總共有1000行。樣本主要...
k近鄰(k-Nearest Neighbor,kNN)算法是經(jīng)典的帶監(jiān)督的分類算法,核心思想是如果一個樣本在特征空間中的k個最相鄰的樣本中的大多數(shù)屬于某一個類別,則針對該樣本的劃分結(jié)果也屬于這個類別。 1. 算法步驟 準(zhǔn)備訓(xùn)練數(shù)據(jù)和測試數(shù)據(jù); 確定參數(shù) k; 計算測試數(shù)據(jù)與各個訓(xùn)練數(shù)據(jù)之間的距離,距離的遞增關(guān)系進(jìn)行排序; 選取距離最小的 k 個點; 確定前 k 個點所在類別的出現(xiàn)頻率; 返回前 ...
摘要:背景近鄰算法的概述近鄰算法的簡介近鄰算法是屬于一個非常有效且易于掌握的機(jī)器學(xué)習(xí)算法,簡單的說就是采用測量不同特征值之間距離的方法對數(shù)據(jù)進(jìn)行分類的一個算法。完美的分類器的錯誤率為,而最差的分類器的錯誤率則為。 1 背景 1.1 k近鄰算法的概述 (1)k近鄰算法的簡介 k-近鄰算法是屬于一個非...
閱讀 1754·2021-11-25 09:43
閱讀 1789·2021-11-24 10:41
閱讀 3108·2021-09-27 13:36
閱讀 816·2019-08-30 15:53
閱讀 3574·2019-08-30 15:44
閱讀 870·2019-08-30 14:03
閱讀 2578·2019-08-29 16:38
閱讀 1003·2019-08-29 13:23