這篇文章適合那些剛接觸Kaggle、想盡快熟悉Kaggle而且獨立完成一個競賽項目的網友,對於已經在Kaggle上參勝過的網友來講,大可沒必要耗費時間閱讀本文。本文分爲兩部分介紹Kaggle,第一部分簡單介紹Kaggle,第二部分將展現解決一個競賽項目的全過程。若有錯誤,請指正!html
一、Kaggle簡介
企業或者研究者能夠將數據、問題描述、指望的指標發佈到Kaggle上,以競賽的形式向廣大的數據科學家徵集解決方
案,相似於KDD-CUP(國際知識發現和數據挖掘競賽)。Kaggle上的參賽者將數據下載下來,分析數據,而後運用機
器學習、數據挖掘等知識,創建算法模型,解決問題得出結果,最後將結果提交,若是提交的結果符合指標要求而且在參賽者中排名第一,將得到比賽豐厚的獎金。更多內容能夠參閱:大數據衆包平臺
下面我以圖文的形式介紹Kaggle:
進入Kaggle網站:
這是當前正在火熱進行的有獎比賽,有冠軍盃形狀的是「Featured」,譯爲「號召」,召集數據科學高手去參賽。下面那個灰色的有試劑瓶形狀的是「Research」,獎金少一點。這兩個類別的比賽是有獎競賽,難度天然不小,做爲入門者,應該先作練習賽:
左圖的比賽是「101」,右圖的是「Playground」,都是練習賽,適合入門。入門Kaggle最好的方法就是獨立完成101和playground這兩個級別的競賽項目。本文的第二部分將選101中的「Digit Recognition」做爲講解。
點擊進入賽題「Digit Recognition」:
這是一個識別數字0~9的練習賽,「Competition Details「是這個比賽的描述,說明參賽者須要解決的問題。」Get the Data「是數據下載,參賽者用這些數據來訓練本身的模型,得出結果,數據通常都是以csv格式給出:
其中,train.csv就是訓練樣本,test.csv就是測試樣本,因爲這個是訓練賽,因此還提供了兩種解決方案,knn_benchmark.R和rf_benchmark.R,前者是用R語。言寫的knn算法程序,後者是用R語言寫的隨機森林算法程序,它們的結果分別是knn_benchmark.csv和rf_benchmark.csv。關於csv格式文件,我前一篇文章有詳述:【Python】csv模塊的使用。
得出結果後,接下來就是提交結果」Make a submission「:
要求提交的文件是csv格式的,假如你將結果保存在result.csv,那麼點擊」Click or drop submission here「,選中result.csv文件上傳便可,系統將測試你提交的結果的準確率,而後排名。
另外,除了「Competition Details「、」Get the Data「、」Make a submission「,側邊欄的」Home「、」Information「、"Forum"等,也提供了關於競賽的一些相關信息,包括排名、規則、輔導......
【以上是第一部分,暫且寫這麼多,有補充的之後再更】
二、競賽項目解題全過程
(1)知識準備
首先,想解決上面的題目,仍是須要一點ML算法的基礎的,另外就是要會用編程語言和相應的第三方庫來實現算法,經常使用的有:
Python以及對應的庫numpy、scipy、scikit-learn(實現了ML的一些算法,能夠直接用)、theano(DeepLearning的算法包)。
R語言、weka
若是用到深度學習的算法,cuda、caffe也能夠用
總之,使用什麼編程語言、什麼平臺、什麼第三方庫都無所謂,不管你用什麼方法,Kaggle只須要你線上提交結果,線下你如何實現算法是沒有限制的。
(2)Digit Recognition解題過程
下面我將採用kNN算法來解決Kaggle上的這道Digit Recognition訓練題。上面提到,我以前用kNN算法實現過,這裏我將直接copy以前的算法的核心代碼,核心代碼是關於kNN算法的主體實現,我再也不贅述,我把重點放在處理數據上。python
如下工程基於Python、numpygit
從」Get the Data「下載如下三個csv文件:github

train.csv是訓練樣本集,大小42001*785,第一行是文字描述,因此實際的樣本數據大小是42000*785,其中第一列的每個數字是它對應行的label,能夠將第一列單獨取出來,獲得42000*1的向量trainLabel,剩下的就是42000*784的特徵向量集trainData,因此從train.csv能夠獲取兩個矩陣trainLabel、trainData。算法
下面給出代碼,另外關於如何從csv文件中讀取數據,參閱:csv模塊的使用編程
- def loadTrainData():
- l=[]
- with open('train.csv') as file:
- lines=csv.reader(file)
- for line in lines:
- l.append(line)
- l.remove(l[0])
- l=array(l)
- label=l[:,0]
- data=l[:,1:]
- return nomalizing(toInt(data)),toInt(label)
這裏還有兩個函數須要說明一下,toInt()函數,是將字符串轉換爲整數,由於從csv文件讀取出來的,是字符串類型的,好比‘253’,而咱們接下來運算須要的是整數類型的,所以要轉換,int(‘253’)=253。toInt()函數以下:數據結構
- def toInt(array):
- array=mat(array)
- m,n=shape(array)
- newArray=zeros((m,n))
- for i in xrange(m):
- for j in xrange(n):
- newArray[i,j]=int(array[i,j])
- return newArray
nomalizing()函數作的工做是歸一化,由於train.csv裏面提供的表示圖像的數據是0~255的,爲了簡化運算,咱們能夠將其轉化爲二值圖像,所以將全部非0的數字,即1~255都歸一化爲1。nomalizing()函數以下:app
- def nomalizing(array):
- m,n=shape(array)
- for i in xrange(m):
- for j in xrange(n):
- if array[i,j]!=0:
- array[i,j]=1
- return array
test.csv裏的數據大小是28001*784,第一行是文字描述,所以實際的測試數據樣本是28000*784,與train.csv不一樣,沒有label,28000*784即28000個測試樣本,咱們要作的工做就是爲這28000個測試樣本找出正確的label。因此從test.csv咱們能夠獲得測試樣本集testData,代碼以下:編程語言
- def loadTestData():
- l=[]
- with open('test.csv') as file:
- lines=csv.reader(file)
- for line in lines:
- l.append(line)
-
- l.remove(l[0])
- data=array(l)
- return nomalizing(toInt(data))
前面已經提到,因爲digit recognition是訓練賽,因此這個文件是官方給出的參考結果,原本能夠不理這個文件的,可是我下面爲了對比本身的訓練結果,因此也把knn_benchmark.csv這個文件讀取出來,這個文件裏的數據是28001*2,第一行是文字說明,能夠去掉,第一列表示圖片序號1~28000,第二列是圖片對應的數字。從knn_benchmark.csv能夠獲得28000*1的測試結果矩陣testResult,代碼:函數
- def loadTestResult():
- l=[]
- with open('knn_benchmark.csv') as file:
- lines=csv.reader(file)
- for line in lines:
- l.append(line)
-
- l.remove(l[0])
- label=array(l)
- return toInt(label[:,1])
到這裏,數據分析和處理已經完成,咱們得到的矩陣有:trainData、trainLabel、testData、testResult
- def classify(inX, dataSet, labels, k):
- inX=mat(inX)
- dataSet=mat(dataSet)
- labels=mat(labels)
- dataSetSize = dataSet.shape[0]
- diffMat = tile(inX, (dataSetSize,1)) - dataSet
- sqDiffMat = array(diffMat)**2
- sqDistances = sqDiffMat.sum(axis=1)
- distances = sqDistances**0.5
- sortedDistIndicies = distances.argsort()
- classCount={}
- for i in range(k):
- voteIlabel = labels[0,sortedDistIndicies[i]]
- classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
- sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
- return sortedClassCount[0][0]
關於這個函數,參考:kNN算法實現數字識別
簡單說明一下,inX就是輸入的單個樣本,是一個特徵向量。dataSet是訓練樣本,對應上面的trainData,labels對應trainLabel,k是knn算法選定的k,通常選擇0~20之間的數字。這個函數將返回inX的label,即圖片inX對應的數字。
對於測試集裏28000個樣本,調用28000次這個函數便可。
kaggle上要求提交的文件格式是csv,上面咱們獲得了28000個測試樣本的label,必須將其保存成csv格式文件才能夠提交,關於csv,參考:【Python】csv模塊的使用。
代碼:
- def saveResult(result):
- with open('result.csv','wb') as myFile:
- myWriter=csv.writer(myFile)
- for i in result:
- tmp=[]
- tmp.append(i)
- myWriter.writerow(tmp)
上面各個函數已經作完了全部須要作的工做,如今須要寫一個函數將它們組合起來解決digit recognition這個題目。咱們寫一個handwritingClassTest函數,運行這個函數,就能夠獲得訓練結果result.csv。
- def handwritingClassTest():
- trainData,trainLabel=loadTrainData()
- testData=loadTestData()
- testLabel=loadTestResult()
- m,n=shape(testData)
- errorCount=0
- resultList=[]
- for i in range(m):
- classifierResult = classify(testData[i], trainData, trainLabel, 5)
- resultList.append(classifierResult)
- print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, testLabel[0,i])
- if (classifierResult != testLabel[0,i]): errorCount += 1.0
- print "\nthe total number of errors is: %d" % errorCount
- print "\nthe total error rate is: %f" % (errorCount/float(m))
- saveResult(resultList)
運行這個函數,能夠獲得result.csv文件:
2 0 9 9 3 7 0 3.......就是每一個圖片對應的數字。與參考結果knn_benchmark.csv比較一下:
28000個樣本中有1004個與kknn_benchmark.csv中的不同。錯誤率爲3.5%,這個效果並很差,緣由是我並未將全部訓練樣本都拿來訓練,由於太花時間,我只取一半的訓練樣原本訓練,即上面的結果對應的代碼是:
- classifierResult = classify(testData[i], trainData[0:20000], trainLabel[0:20000], 5)
訓練一半的樣本,程序跑了將近70分鐘(在我的PC上)。
將result.csv整理成kknn_benchmark.csv那種格式,即加入第一行文字說明,加入第一列的圖片序號,而後make a submission,結果準確率96.5%:
【完】