概述
这是一个分类任务。每个例子都有2个分类结果和11392个维度特征。一共有2177020个训练样例和220245个测试样例。
你会被提供以下三个文件:
-
train.txt
每一行的格式如下:
label index0:value0 index2:value2 index3:value3 ...
value0, value1,...都是特征(如果value0等于0它将会被省略),总共只有2个分类label。
-
test.txt
这个文件包含一些需要你预测label的特征。每一行的格式如下:
id index0:value0 index1:value1 index2:value2 ...
-
sample_submission.csv
你需要提交的文件应该包含以下格式,每一行如下:
id,label
这个问题的评估矩阵是Categorization Accuracy(multiclass-classification)。输出文件应该包含一个头部和以下格式:
id,label
0,1
1,0
2,1
3,0
etc.
方法一:Liblinear
我有尝试过常规方法,但是都有内存不够用的问题。因为训练数据规模太大了,就连特征维度也高达11392,所以都不适用。
Liblinear是一个简单的求解大规模规则化线性分类和回归的软件包,它的速度比较快,而且对大规模数据有内存优化,适用于个人电脑。
我的实验环境为windows 10 64-bit。关于train程序的参数设置,分类器为 L2-regularized L2-loss support vectorclassification (dual),cost为1,设置epsilon-SVR的损失函数的参数epsilon为0.1。用predict程序跑出来的数据提交到kaggle的分数0.5733。
方法二:Neural Network + Keras
keras是一个深度学习框架,基于Theano,可使用GPU做加速运算。
我的实验环境为windows 10 64-bit、Pycharm和Keras,使用语言为Python 3.5。
以下为实验步骤:
1. 对train.txt和test.txt做分割
因为train.txt的训练样例太多了,不可能同时装进一个矩阵进行运算,所以需要做分割成小文件。我把它分成了train文件夹下的200个part小文件。代码如下:
# Preprocess for train
partnums = 200
inputfile = open("train.txt", "rb")
outputlist = []
for i in range(partnums):
outputlist.append(open('train/part%04d'%i,'wb'))
index = 0
while True:
chunk = inputfile.readline()
if not chunk:
break
outputlist[index].write(chunk)
index += 1
if index == partnums:
index = 0
for i in range(partnums):
outputlist[i].close()
同理,也把test.txt分割成test文件夹下的20个小文件。
2. 建立神经网络模型
我选用了keras框架的Sequence模型。
隐含层为一层有300个节点的Dense层,其激活函数为Relu。ReLu的使用,使得网络可以自行引入稀疏性,同时使学习周期大大缩短。
输出层为有1个节点的Dense层,其激活函数为Sigmoid。Sigmoid的使用,可以将上一层的结果映射到 [0, 1] 的区间内,输出结果为1的概率。
同时,损耗函数为binary_crossentropy,优化器为rmsprop,以下为建模代码:
# build model
print("building model:")
model = Sequential()
model.add(Dense(300, input_shape=(11392, ),activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
checkpointer = ModelCheckpoint(filepath="weights.hdf5", verbose=1, save_best_only=True)
3. 分批训练
逐个读入train文件夹下的各个小文件,将样例的信息还原成一个11392维度的特征矩阵,并提取出train_X和train_y,对模型进行分批训练。批训练样例大小为50,迭代次数为10,验证分割比例为0.05。
以下为训练代码:
# batch train
print("batch training")
partnums = 200
width = 11392
for i in range(partnums):
lines = open('train/part%04d' % i).readlines()
print("reading the %04d part of train: " % i)
depth = len(lines)
print("depth:", depth)
# generate train_X and train_y
train_X = [[0 for _ in range(width)] for __ in range(depth)]
train_y = [0 for _ in range(depth)]
for y, line in enumerate(lines):
datas = line.split(' ')
train_y[y] = int(datas[0])
datas.pop(0)
for data in datas:
x = int(data.split(':')[0]) - 1
train_X[y][x] = 1
del x
del datas
print("", len(train_X[0]))
model.fit(train_X, train_y, batch_size=50, nb_epoch=10, validation_split=0.05, callbacks=[checkpointer])
del lines
del train_X
del train_y
同时要注意的是,需要在每次迭代后,把临时变量回收掉,不然内存同样不够用。每次训练所使用的内存空间大概为2GB。
4. 分批预测并保存结果
由于test.txt被分割成了20个小文件,所以需要分批预测20次。
因为预测结果是 [0,1] 区间之间的浮点数概率,所以需要做转换处理。当概率大于0.5时,预测结果为1;否则,预测结果为0。同时,合并预测结果写到 submission.csv 文件里。
以下为代码:
# predict
print("predicting:")
output = open("submission.csv", "w")
output.write("Id,label
")
width = 11392
for i in range(20):
print("reading part %04d of test" % i)
lines = open("test/part%04d" % i).readlines()
x_test = [[0 for _ in range(width)] for __ in range(len(lines))]
indexs = []
for y, line in enumerate(lines):
datas = line.split(' ')
indexs.append(datas[0])
datas.pop(0)
for data in datas:
x = int(data.split(':')[0]) - 1
x_test[y][x] = 1
del x
del datas
predicted = model.predict(x_test)
for j in range(len(indexs)):
if float(predicted[j]) >= 0.5:
output.write("%s,%d
" % (indexs[j], 1))
else:
output.write("%s,%d
" % (indexs[j], 0))
del lines
del indexs
del predicted
output.close()
5. 总结
本次实验在本地机器上的val_acc最高可以达到0.91,但是把结果提交到kaggle上的分数为0.53。
而且在对前10个train小文件训练完后,val_acc就达到最佳了,后续训练参数似乎无改进。
以下为前3次训练的log结果:
第1次训练:
第2次训练:
第3次训练: