Otto Group Product Classification

简介

Otto Group Product Classification Challenge是Kaggle上目前正在进行的一个比赛,目前已1000+队伍参赛,由Otto公司赞助1W美刀,数据也是来自于该公司的产品,提供了train.csv、test.csv、samplesubmission.csv三份数据。train.csv里包含了6万多个样本,每个样本有一个id,93个特征值feat_1~feat_93,以及类别target,一共9种类别:class_1~class_9。test.csv里有14万多测试样本,只有id以及93个特征,参赛者的任务是对这些样本分类。

提交结果的格式

官网上给出的格式:

id,Class_1,Class_2,Class_3,Class_4,Class_5,Class_6,Class_7,Class_8,Class_91,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.02,0.0,0.2,0.3,0.3,0.0,0.0,0.1,0.1,0.0

也就是说,可以不用给出确切的类别,给出属于各个类别的概率也行。这一点很重要,我一开始没注意看,浪费了许多精力瞎折腾。所以但凡比赛,官网给出的信息最好都仔细看一遍。

评分标准

评分的公式见:这里

我稍微解释一下这条公式,i表示样本,j表示类别。Pij代表第i个样本属于类别j的概率,如果第i个样本真的属于类别j,,则yij等于1,否则为0。

假如你将所有的测试样本都正确分类,所有pij都是1,那每个log(pij)都是0,最终的logloss也是0。

假如第1个样本本来是属于1类别的,但是你给它的类别概率pij=0.1,那logloss就会累加上log(0.1)这一项。我们知道这一项是负数,而且pij越小,负得越多,如果pij=0,将是无穷。这会导致这种情况:你分错了一个,logloss就是无穷。这当然不合理,为了避免这一情况,官方是这样处理的:

也就是说最小不会小于10^-15。

开始解题

废话终于说完,进入主题。下面讲一个很naive的solution,基本上不用动脑,只要会简单地使用sklearn、numpy,就能打败目前一半的参赛队伍。

代码放在我的github上wepe/Kaggle-Solution,分几部分来讲:

数据预处理

严格来说,我并没有做多少数据预处理的工作。只是一些加载数据的函数,分别是 loadTrainSet()和loadTestSet(),加载训练数据集和测试数据集。代码如下,里面顺便做了归一化以及零均值(这里不做standardize差别也不大)。

:traindata = []trainlabel = []table = {“Class_1″:1,”Class_2″:2,”Class_3″:3,”Class_4″:4,”Class_5″:5,”Class_6″:6,”Class_7″:7,”Class_8″:8,”Class_9”:9}with open(“train.csv”) as f:rows = csv.reader(f)rows.next()for row in rows:l = []for i in range(1,94):l.append(int(row[i]))traindata.append(l)trainlabel.append(table.get(row[-1]))f.close()traindata = np.array(traindata,dtype=”float”)trainlabel = np.array(trainlabel,dtype=”int”)#Standardize(zero-mean,nomalization)mean = traindata.mean(axis=0)std = traindata.std(axis=0)traindata = (traindata – mean)/std#shuffle the datarandomIndex = [i for i in xrange(len(trainlabel))]random.shuffle(randomIndex)traindata = traindata[randomIndex]trainlabel = trainlabel[randomIndex]return traindata,trainlabel:testdata = []with open(“test.csv”) as f:rows = csv.reader(f)rows.next()for row in rows:l = []for i in range(1,94):l.append(int(row[i]))testdata.append(l)f.close()testdata = np.array(testdata,dtype=”float”)#Standardize(zero-mean,nomalization)mean = testdata.mean(axis=0)std = testdata.std(axis=0)testdata = (testdata – mean)/stdreturn testdata

代码挺长的,但其实都是些简单的读取和处理工作。(如果不想写这么繁琐的代码,可以试试数据分析包pandas,几行代码完成这些工作)。

模型评估

模型评估一般都是从训练数据集中分出一部分来做validation,一般我们是用validation accuracy来评估的(如上所述),但是这个比赛既然官方给出了评估公式,我们就根据这个公式写个评估函数:

:num = len(label)logloss = 0.0for i in range(num):p = max(min(pred_label[i][label[i]-1],1-10**(-15)),10**(-15))logloss += np.log(p)logloss = -1*logloss/numreturn logloss

以上三个函数loadTrainSet()、loadTestSet()、evaluation()我都放在代码文件preprocess.py中,此外在该文件中还定义了一个saveResult()函数,根据test set的预测类别test_label生成一个用于提交结果的submission.csv文件。

分类算法

直接调用sklearn里面的随机森林,参数调节:随便调了几次决策树的数目,可以使logloss达到0.5左右,这个得分目前已经打败了一半的参赛队伍。

):print “Start training Random forest…”rfClf = RandomForestClassifier(n_estimators=400,n_jobs=-1)rfClf.fit(train_data,train_label)#evaluate on validation setval_pred_label = rfClf.predict_proba(val_data)logloss = preprocess.evaluation(val_label,val_pred_label)print “logloss of validation set:”,loglossprint “Start classify test set…”test_label = rfClf.predict_proba(test_data)preprocess.saveResult(test_label,filename = name)

这个函数的参数val_data就是验证集数据,从train.csv里面取出6000个构成,大约占1/10的数据。

这部分的代码放在文件RandomForest.py中。

有兴趣的去我github获取代码试试吧。Have Fun!

============

by wepon

没有伞的孩子必须努力奔跑!

Otto Group Product Classification

相关文章:

你感兴趣的文章:

标签云: