標籤:kaggle 機器學習 資料採礦 python
大資料競賽平台——Kaggle 入門篇
這篇文章適合那些剛接觸Kaggle、想儘快熟悉Kaggle並且獨立完成一個競賽項目的網友,對於已經在Kaggle上參賽過的網友來說,大可不必耗費時間閱讀本文。本文分為兩部分介紹Kaggle,第一部分簡單介紹Kaggle,第二部分將展示解決一個競賽項目的全過程。如有錯誤,請指正!
1、Kaggle簡介Kaggle是一個資料分析的競賽平台,網址:https://www.kaggle.com/
企業或者研究者可以將資料、問題描述、期望的指標發布到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"等,也提供了關於競賽的一些相關資訊,包括排名、規則、輔導......
【以上是第一部分,暫且寫這麼多,有補充的以後再更】
2、競賽項目解題全過程(1)知識準備
首先,想解決上面的題目,還是需要一點ML演算法的基礎的,另外就是要會用程式設計語言和相應的第三方庫來實現演算法,常用的有:Python以及對應的庫numpy、scipy、scikit-learn(實現了ML的一些演算法,可以直接用)、theano(DeepLearning的演算法包)。R語言、weka如果用到深度學習的演算法,cuda、caffe也可以用總之,使用什麼程式設計語言、什麼平台、什麼第三方庫都無所謂,無論你用什麼方法,Kaggle只需要你線上提交結果,線下你如何?演算法是沒有限制的。
Ok,下面講解題過程,以”Digit Recognition“為例,數字識別這個問題我之前寫過兩篇文章,分別用kNN演算法和Logistic演算法去實現,有完整的代碼,有興趣可以閱讀:kNN演算法實現數字識別、 Logistic迴歸實現數字識別
(2)Digit Recognition解題過程
下面我將採用kNN演算法來解決Kaggle上的這道Digit Recognition訓練題。上面提到,我之前用kNN演算法實現過,這裡我將直接copy之前的演算法的核心代碼,核心代碼是關於kNN演算法的主體實現,我不再贅述,我把重點放在處理資料上。
以下工程基於Python、numpy
從”Get the Data“下載以下三個csv檔案:
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) #42001*785 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()函數如下:
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) #28001*784 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) #28001*2 l.remove(l[0]) label=array(l) return toInt(label[:,1])
到這裡,資料分析和處理已經完成,我們獲得的矩陣有:trainData、trainLabel、testData、testResult
這裡我們採用kNN演算法來分類,核心代碼:
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%:
下載工程代碼:github地址
【完】
大資料競賽平台——Kaggle 入門