日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【机器学习实验二】k-NN算法—改进约会网站以及手写体数字识别

發布時間:2024/1/8 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【机器学习实验二】k-NN算法—改进约会网站以及手写体数字识别 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

一、改進約會網站

1、項目背景

2、數據收集

3、在約會網站中使用k-近鄰算法的流程

4、代碼實現

二、手寫體數字識別?

1.了解手寫體數字識別

?2、手寫體數字識別思路

?3.1、導入模塊

?3.2、引入訓練樣本文件和測試樣本文件,定義一個讀取數據的轉換數據的函數

3.3、定義一個字段轉列表的函數

?3.4、定義相似度函數

?3.5、編寫識別函數

?3.6、調用

?3.7、運行結果


一、改進約會網站

1、項目背景

? ? ? ? 我的朋友海倫一直使用在線約會網站尋找適合自己的約會對象。盡管約會網站會推薦不同的人選,但她并不是喜歡每一個人。經過一番總結,她發現自己交往過的人可以進行如下分類:

  • 不喜歡的人
  • 魅力一般的人
  • 極具魅力的人

海倫認為,盡管發現了這些規律,仍無法將約會網站推薦的匹配對象歸入恰當的分類,她希望借助我們的分類軟件更好的幫助她將匹配的對象劃分到確切的分類中。

2、數據收集

海倫收集約會數據已經有了一段時間,她把這些數據存放在文本文件datingTestSet.txt中,每個樣本數據占據一行,總共有1000行。

?海倫收集的樣本數據主要包含以下3種特征:

每年獲得的飛行常客里程數
玩視頻游戲所消耗時間百分比
每周消費的冰淇淋公升數

3、在約會網站中使用k-近鄰算法的流程

(1)收集數據:提供文本文件,即datingTestSet.txt。

(2)準備數據:使用Python解析文本文件。

(3)分析數據:使用Matplotlib畫二維擴散圖。

(4)測試算法:使用文本文件的部分數據作為測試樣本,計算錯誤率。

(5)使用算法:錯誤率在可接受范圍內,就可以運行k-近鄰算法進行分類。

4、代碼實現

#-*- coding:utf-8 -*-import matplotlib.lines as mlines import matplotlib.pyplot as plt import numpy as np import matplotlib as mpl import operator''' #準備數據,從文本文件中解析數據 ''' def file2matrix(filename):#打開文件with open(filename,'r') as fr:# 讀取文件所有內容arrayOLines = fr.readlines()# 得到文件行數numberOfLines = len(arrayOLines)# 返回的NumPy矩陣,解析完成的數據:numberOfLines行,3列returnMat = np.zeros((numberOfLines, 3))# 返回的分類標簽向量classLabelVector = []# 行的索引值index = 0for line in arrayOLines:# s.strip(rm),當rm空時,默認刪除空白符(包括'\n','\r','\t',' ')line = line.strip()# 使用s.split(str="",num=string,cout(str))將字符串根據'\t'分隔符進行切片。listFromLine = line.split('\t')# 將數據前三列提取出來,存放到returnMat的NumPy矩陣中,也就是特征矩陣returnMat[index, :] = listFromLine[0:3]# 根據文本中標記的喜歡的程度進行分類,1代表不喜歡,2代表魅力一般,3代表極具魅力if listFromLine[-1] == 'didntLike':classLabelVector.append(1)elif listFromLine[-1] == 'smallDoses':classLabelVector.append(2)elif listFromLine[-1] == 'largeDoses':classLabelVector.append(3)index += 1return returnMat, classLabelVector''' #分析數據,數據可視化,使用Matplotlib創建散點圖 ''' def showdatas(datingDataMat, datingLabels):#設置漢字格式# sans-serif就是無襯線字體,是一種通用字體族。# 常見的無襯線字體有 Trebuchet MS, Tahoma, Verdana, Arial, Helvetica, 中文的幼圓、隸書等等mpl.rcParams['font.sans-serif'] = ['SimHei'] # 指定默認字體 SimHei為黑體mpl.rcParams['axes.unicode_minus'] = False # 用來正常顯示負號#將fig畫布分隔成2行2列,不共享x軸和y軸,fig畫布的大小為(13,8)#當nrow=2,nclos=2時,代表fig畫布被分為四個區域,axs[0][0]表示第一行第一個區域fig, axs = plt.subplots(nrows=2, ncols=2,sharex=False, sharey=False, figsize=(13,9))LabelsColors = []for i in datingLabels:if i == 1:LabelsColors.append('green')if i == 2:LabelsColors.append('red')if i == 3:LabelsColors.append('blue')#畫出散點圖,以datingDataMat矩陣的第一(飛行常客例程)、第二列(玩游戲)數據畫散點數據,散點大小為15,透明度為0.5axs[0][0].scatter(x=datingDataMat[:,0], y=datingDataMat[:,1], color=LabelsColors,s=15, alpha=.5)#設置標題,x軸label,y軸labelaxs0_title_text = axs[0][0].set_title('每年獲得的飛行常客里程數與玩視頻游戲所消耗時間占比')axs0_xlabel_text = axs[0][0].set_xlabel('每年獲得的飛行常客里程數')axs0_ylabel_text = axs[0][0].set_ylabel('玩視頻游戲所消耗時間占')plt.setp(axs0_title_text, size=12, weight='bold', color='red')plt.setp(axs0_xlabel_text, size=10, weight='bold', color='black')plt.setp(axs0_ylabel_text, size=10, weight='bold', color='black')#畫出散點圖,以datingDataMat矩陣的第一(飛行常客例程)、第三列(冰激凌)數據畫散點數據,散點大小為15,透明度為0.5axs[0][1].scatter(x=datingDataMat[:,0], y=datingDataMat[:,2], color=LabelsColors,s=15, alpha=.5)#設置標題,x軸label,y軸labelaxs1_title_text = axs[0][1].set_title('每年獲得的飛行常客里程數與每周消費的冰激淋公升數',)axs1_xlabel_text = axs[0][1].set_xlabel('每年獲得的飛行常客里程數')axs1_ylabel_text = axs[0][1].set_ylabel('每周消費的冰激淋公升數')plt.setp(axs1_title_text, size=12, weight='bold', color='red')plt.setp(axs1_xlabel_text, size=10, weight='bold', color='black')plt.setp(axs1_ylabel_text, size=10, weight='bold', color='black')#畫出散點圖,以datingDataMat矩陣的第二(玩游戲)、第三列(冰激凌)數據畫散點數據,散點大小為15,透明度為0.5axs[1][0].scatter(x=datingDataMat[:,1], y=datingDataMat[:,2], color=LabelsColors,s=15, alpha=.5)#設置標題,x軸label,y軸labelaxs2_title_text = axs[1][0].set_title('玩視頻游戲所消耗時間占比與每周消費的冰激淋公升數')axs2_xlabel_text = axs[1][0].set_xlabel('玩視頻游戲所消耗時間占比')axs2_ylabel_text = axs[1][0].set_ylabel('每周消費的冰激淋公升數')plt.setp(axs2_title_text, size=12, weight='bold', color='red')plt.setp(axs2_xlabel_text, size=10, weight='bold', color='black')plt.setp(axs2_ylabel_text, size=10, weight='bold', color='black')#設置圖例didntLike = mlines.Line2D([], [], color='green', marker='.', markersize=6, label='不喜歡')smallDoses = mlines.Line2D([], [], color='red', marker='.',markersize=6, label='魅力一般')largeDoses = mlines.Line2D([], [], color='blue', marker='.',markersize=6, label='極具魅力')#添加圖例axs[0][0].legend(handles=[didntLike,smallDoses,largeDoses])axs[0][1].legend(handles=[didntLike,smallDoses,largeDoses])axs[1][0].legend(handles=[didntLike,smallDoses,largeDoses])#顯示圖片plt.show()''' #準備數據,數據歸一化處理 ''' def autoNorm(dataSet):#獲得每列數據的最小值和最大值minVals = dataSet.min(0)maxVals = dataSet.max(0)#最大值和最小值的范圍ranges = maxVals - minVals#shape(dataSet)返回dataSet的矩陣行列數#normDataSet = np.zeros(np.shape(dataSet))#返回dataSet的行數m = dataSet.shape[0]#原始值減去最小值normDataSet = dataSet - np.tile(minVals, (m, 1))#除以最大和最小值的差,得到歸一化數據normDataSet = normDataSet / np.tile(ranges, (m, 1))#返回歸一化數據結果,數據范圍,最小值return normDataSet, ranges, minVals''' KNN算法分類器 # inX - 用于分類的數據(測試集) # dataSet - 用于訓練的數據(訓練集) # labes - 訓練數據的分類標簽 # k - kNN算法參數,選擇距離最小的k個點 # sortedClassCount[0][0] - 分類結果 ''' def classify0(inX, dataSet, labels, k):#numpy函數shape[0]返回dataSet的行數dataSetSize = dataSet.shape[0]#在列向量方向上重復inX共1次(橫向),行向量方向上重復inX共dataSetSize次(縱向)diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet#二維特征相減后平方sqDiffMat = diffMat**2#sum()所有元素相加,sum(0)列相加,sum(1)行相加sqDistances = sqDiffMat.sum(axis=1)#開方,計算出距離distances = sqDistances**0.5#返回distances中元素從小到大排序后的索引值sortedDistIndices = distances.argsort()#定一個記錄類別次數的字典classCount = {}for i in range(k):#取出前k個元素的類別voteIlabel = labels[sortedDistIndices[i]]#dict.get(key,default=None),字典的get()方法,返回指定鍵的值,如果值不在字典中返回默認值。#計算類別次數classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1#python3中用items()替換python2中的iteritems()#key=operator.itemgetter(1)根據字典的值進行排序#key=operator.itemgetter(0)根據字典的鍵進行排序#reverse降序排序字典sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)#返回次數最多的類別,即所要分類的類別return sortedClassCount[0][0]''' #測試算法,計算分類器的準確率,驗證分類器 ''' def datingClassTest():#打開的文件名filename = "datingTestSet.txt"#將返回的特征矩陣和分類向量分別存儲到datingDataMat和datingLabels中datingDataMat, datingLabels = file2matrix(filename)#取所有數據的百分之十hoRatio = 0.10#數據歸一化,返回歸一化后的矩陣,數據范圍,數據最小值normMat, ranges, minVals = autoNorm(datingDataMat)#獲得normMat的行數m = normMat.shape[0]#百分之十的測試數據的個數numTestVecs = int(m * hoRatio)#分類錯誤計數errorCount = 0.0for i in range(numTestVecs):#前numTestVecs個數據作為測試集,后m-numTestVecs個數據作為訓練集classifierResult = classify0(normMat[i,:], normMat[numTestVecs:m,:],datingLabels[numTestVecs:m], 4)print("分類結果:%d\t真實類別:%d" % (classifierResult, datingLabels[i]))if classifierResult != datingLabels[i]:errorCount += 1.0print("錯誤率:%f%%" %(errorCount/float(numTestVecs)*100))''' #使用算法,構建完整可用系統 ''' def classifyPerson():#輸出結果resultList = ['不喜歡','有些喜歡','非常喜歡']#三維特征用戶輸入ffMiles = float(input("每年獲得的飛行常客里程數:"))precentTats = float(input("玩視頻游戲所耗時間百分比:"))iceCream = float(input("每周消費的冰激淋公升數:"))#打開的文件名filename = "datingTestSet.txt"#打開并處理數 據datingDataMat, datingLabels = file2matrix(filename)#訓練集歸一化normMat, ranges, minVals = autoNorm(datingDataMat)#生成NumPy數組,測試集inArr = np.array([ffMiles,precentTats, iceCream])#測試集歸一化norminArr = (inArr - minVals) / ranges#返回分類結果classifierResult = classify0(norminArr, normMat, datingLabels, 3)#打印結果print("你可能%s這個人" % (resultList[classifierResult-1]))''' #主函數,測試以上各個步驟,并輸出各個步驟的結果 ''' if __name__ == '__main__':#打開的文件名filename = "datingTestSet.txt"#打開并處理數據datingDataMat, datingLabels = file2matrix(filename)#數據可視化showdatas(datingDataMat, datingLabels)#驗證分類器datingClassTest()#使用分類器classifyPerson()

項目運行結果:

(1)數據可視化:

?

(2)?驗證分類器計算錯誤率結果

(3)使用分類器根據輸入數據獲得預測結果

二、手寫體數字識別?

1.了解手寫體數字識別

我們通過畫圖,或者在紙上寫上數字或字母,將照片進行處理,得到固定的照片規格,將照片轉換為文本0,1表示的內容。例如下圖:?

?

?2、手寫體數字識別思路

將測試數據轉換成只有一列的0-1矩陣形式 將所有(N個)訓練數據也都用上方法轉換成只有一列的0-1矩陣形式

把N個單列數據存入新矩陣A中——矩陣A每一列存儲一個字的所有信息

用測試數據與矩陣A中的每一列求距離,求得的N個距離存入距離數組中

從距離數組中取出最小的K個距離所對應的訓練集的索引 擁有最多索引的值就是預測值
?

?3.1、導入模塊

import os,time,operator #導入os內置庫來讀取文件名 導入time來測試效率 import pandas as pd #導入數據處理庫pandas 安裝方法pip install pandas import numpy as np #導入科學計算庫numpy 安裝方法pip install numpy import matplotlib.pyplot as plt #導入繪圖庫matplotlib 安裝方法pip install matplotlib

?3.2、引入訓練樣本文件和測試樣本文件,定義一個讀取數據的轉換數據的函數

trainingDigits =r'D:\機器學習代碼\MLiA_SourceCode\machinelearninginaction\Ch02\digits\trainingDigits' testDigits = r'D:\機器學習代碼\MLiA_SourceCode\machinelearninginaction\Ch02\digits\testDigits'## ↑數據路徑 tarining = (os.listdir(trainingDigits)) ## 讀取訓練集 test = (os.listdir(testDigits)) ## 讀取測試集 def read_file(doc_name): ## 定義一個把32x32格式轉為1行的函數data=np.zeros((1,1024)) ## 創建1個zero數組f=open(doc_name) ## 打開文件for i in range(32): ## 已知每個文件中有32行32列hang=f.readline() ## 取行for j in range(32): ## 取每行中的每一列data[0,32*i+j]=int(hang[j]) ## 給data值# print(pd.DataFrame(data)) ## 不要在這里轉換成DataFrame。return data ## 否則測試集效率會降低7倍## 讀取訓練集效率會降低12倍

3.3、定義一個字段轉列表的函數

def dict_list(dic:dict): ## 定義函數將字典轉化為列表keys = dic.keys() ## dic.keys()就是字典的kvalues = dic.values() ## dic.values()就是字典的Vlst = [(key,val) for key,val in zip(keys, values)] ## for k,v in zip(k,v)return lst ## zip是一個可迭代對象## 返回一個列表

?3.4、定義相似度函數

def xiangsidu(tests,xunlians,labels,k): ## tests:測試集 # xulians:訓練樣本集 # labels:標簽 # k: 鄰近的個數data_hang=xunlians.shape[0] ## 獲取訓練集的行數data_hangzu=np.tile(tests,(data_hang,1))-xunlians ## 用tile把測試集tests重構成一個 data_hang行、1列的1維數組q=np.sqrt((zu**2).sum(axis=1)).argsort() ## 計算完距離后從低到高排序,argsort返回的是索引my_dict = {} ## 設置一個dictfor i in range(k): ## 根據我們的k來統計出現頻率,樣本類別votelabel=labels[q[i]] ## q[i]是索引值,通過labels來獲取對應標簽my_dict[votelabel] = my_dict.get(votelabel,0)+1 ## 統計每個標簽的次數sortclasscount=sorted(dict_list(my_dict),key=operator.itemgetter(1),reverse=True)## 獲取votelabel鍵對應的值,無返回默認return sortclasscount[0][0] ## 返回出現頻次最高的類別

?3.5、編寫識別函數

def shibie(): ## 定義一個識別手寫數字的函數label_list = [] ## 將訓練集存儲到一個矩陣并存儲他的標簽train_length = len(tarining) ## 直接一次獲取訓練集長度train_zero = np.zeros((train_length,1024)) ## 創建(訓練集長度,1024)維度的zeros數組for i in range(train_length): ## 通過遍歷訓練集長度doc_name = tarining[i] ## 獲取所有的文件名file_label = int(doc_name[0]) ## 取文件名第一位文件的標簽label_list.append(file_label) ## 將標簽添加至handlabel中train_zero[i,:] = read_file(r'%s\%s'%(trainingDigits,doc_name))## 轉成1024的數組## 下面是測試集errornum = 0 ## 記錄error的初值testnum = len(test) ## 同上 獲取測試集的長度errfile = [] ## 定義一個空列表for i in range(testnum): ## 將每一個測試樣本放入訓練集中使用KNN進行測試testdoc_name = test[i] ## 通過i當作下標來獲取測試集里面的文件test_label = int(testdoc_name[0]) ## 拿到測試文件的名字 拿到我們的數字標簽testdataor = read_file(r'%s\%s' %(testDigits,testdoc_name)) ## 調用read_file操作測試集result = xiangsidu(testdataor, train_zero, label_list, 3) ## 調用xiangsidu返回了resultprint("正在測試 %d, 內容是 %d" % (test_label,result)) ## 輸出result和標簽if (result != test_label): ## 判斷標簽是否等于測試名errornum += 1 ## 不是則+1 記錄次數errfile.append(testdoc_name) ## 并把錯誤的文件名加入錯誤列表print("錯誤數量有 :%d" % errornum) ## 輸出錯誤的數量print("錯誤的有 :%s"%[i for i in errfile]) ## 輸出錯誤的列表中的名字print("準確率 %.2f%%" % ((1 - (errornum / float(testnum))) * 100)) ## 計算準確率

?3.6、調用

if __name__ == '__main__': ## 聲明主函數a = time.time() ## 設置起始時間shibie() ## 調用測試函數b= time.time() - a ## 計算運行時間print("運行時間:",b) ## 輸出運行時間

?3.7、運行結果

總結

以上是生活随笔為你收集整理的【机器学习实验二】k-NN算法—改进约会网站以及手写体数字识别的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。