關於kaggle-----Digital Recognition(數字識別)項目的算法詳解,
題目鏈接:
https://www.kaggle.com/c/digit-recognizer
需說明,因爲本題目使用了KNN算法,所以運行時會十分緩慢,本條也在KNN算法的詳解中有提到,如果做嘗試需等待很長時間,實際運行出的數據爲2w8,可根據運行中的打印輸出內容推算處理時間。
全代碼
以下爲項目全代碼,內附逐條註釋,可以按照註釋理解,後部分附詳情解答。
import numpy as np
import pandas as pd
import operator
import csv
# inX:進行類別判斷的一條數據
# trainSet:訓練數據
# labels:每條數據對應的標籤
# k:近鄰數量
def classify(inX, trainSet, labels, k):
#shape[0]得出trainSet的行數,即樣本個數
trainSetSize = trainSet.shape[0]
#tile(A,(m,n))將數組A作爲元素構造m行n列的數組
diffMatrix = np.tile(inX, (trainSetSize, 1)) - trainSet
sqDiffMatrix = diffMatrix ** 2
#array.sum(axis=1)按行累加,axis=0爲按列累加
sqDistance = sqDiffMatrix.sum(axis=1)
distances = sqDistance ** 0.5
# argsort() 返回排序索引
sortedDistanceIndices = distances.argsort()
#sortedDistIndicies[0]表示排序後排在第一個的那個數在原來數組中的下標
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistanceIndices[i]]
#get(key,x)從字典中獲取key對應的value,沒有key的話返回0
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
#sorted()函數,按照第二個元素即value的次序逆向(reverse=True)排序
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
def DigitRecognition():
# 構造訓練集和測試集
pdTrainData = pd.read_csv("路徑/train.csv")
# 轉換成array對象
trainSet = pdTrainData.values
# 對array對象進行切片操作
trainSetLabels = trainSet[:, 0]
# 將標籤數據從訓練數據集中剔除,方便和測試數據進行數值運算
trainSet = trainSet[:, 1:]
pdTestData = pd.read_csv("路徑/test.csv")
testSet = pdTestData.values
# 保存結果的列表
index = []
result = []
# 對測試集中的每條數據進行處理
for i in range(testSet.shape[0]):
print("開始判斷第%d條數據"%i)
index.append(i + 1)
predictNum = classify(testSet[i], trainSet, trainSetLabels, 3)
result.append(predictNum)
# 將數據保存到csv文件中
predictions = pd.DataFrame({"ImageId":index, "Label":result})
predictions.to_csv("路徑/submission.csv", index=False)
DigitRecognition()
詳情解答
第一部分:KNN算法模塊
KNN算法詳解鏈接:
https://blog.csdn.net/weixin_41744624/article/details/104694204
本部分步驟:
- 得出訓練集的行數。(根據KNN算法,kaggle已經將訓練集轉換爲了每個數字信息爲1行的矩陣,一共n行的n條數據,此步驟爲獲取訓練集中的數據個數)
- 把inX(也就是我們需要判別是什麼數字的數據),轉換成和訓練集中,一樣行數的,僅有1列的數組矩陣
- diffmatrix是被測試的向量inX變化的矩陣與訓練集的矩陣相減而得的矩陣(也就是我們所定義的求被測試的向量與訓練集中點的距離)
- 根據每一條求得的距離做按列加和,也就是總距離sqDistance
- 執行k次選取排序,臨近的出現距離最小的k個點做記錄,出現類別最多的就是這個被測試點inX的類別
import numpy as np
import pandas as pd
import operator
import csv
# inX:進行類別判斷的一條數據
# trainSet:訓練數據
# labels:每條數據對應的標籤
# k:近鄰數量
def classify(inX, trainSet, labels, k):
#shape[0]得出trainSet的行數,即樣本個數
trainSetSize = trainSet.shape[0]
#tile(A,(m,n))將數組A作爲元素構造m行n列的數組
diffMatrix = np.tile(inX, (trainSetSize, 1)) - trainSet
sqDiffMatrix = diffMatrix ** 2
#array.sum(axis=1)按行累加,axis=0爲按列累加
sqDistance = sqDiffMatrix.sum(axis=1)
distances = sqDistance ** 0.5
# argsort() 返回排序索引
sortedDistanceIndices = distances.argsort()
#sortedDistIndicies[0]表示排序後排在第一個的那個數在原來數組中的下標
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistanceIndices[i]]
#get(key,x)從字典中獲取key對應的value,沒有key的話返回0
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
#sorted()函數,按照第二個元素即value的次序逆向(reverse=True)排序
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
第二部分:數據使用模塊
- 讀取訓練集數據,將數據轉化爲array對象(爲了執行切片操作)
- 剔除第一行的名稱,再剔除第一列的標籤(kaggle數據訓練集中有介紹存在標籤列)
- 測試集做同樣的處理
- 保存到提交文件中
def DigitRecognition():
# 構造訓練集和測試集
pdTrainData = pd.read_csv("路徑/train.csv")
# 轉換成array對象
trainSet = pdTrainData.values
# 對array對象進行切片操作
trainSetLabels = trainSet[:, 0]
# 將標籤數據從訓練數據集中剔除,方便和測試數據進行數值運算
trainSet = trainSet[:, 1:]
pdTestData = pd.read_csv("路徑/test.csv")
testSet = pdTestData.values
# 保存結果的列表
index = []
result = []
# 對測試集中的每條數據進行處理
for i in range(testSet.shape[0]):
print("開始判斷第%d條數據"%i)
index.append(i + 1)
predictNum = classify(testSet[i], trainSet, trainSetLabels, 3)
result.append(predictNum)
# 將數據保存到csv文件中
predictions = pd.DataFrame({"ImageId":index, "Label":result})
predictions.to_csv("路徑/submission.csv", index=False)