大规模分类问题作业报告

概述

这是一个分类任务。每个例子都有2个分类结果和11392个维度特征。一共有2177020个训练样例和220245个测试样例。

你会被提供以下三个文件:

  1. train.txt

    每一行的格式如下:

     label index0:value0 index2:value2 index3:value3 ...
    

    value0, value1,...都是特征(如果value0等于0它将会被省略),总共只有2个分类label。

  2. test.txt

    这个文件包含一些需要你预测label的特征。每一行的格式如下:

     id index0:value0 index1:value1 index2:value2 ...
    
  3. 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("width:", 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\n")
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\n" % (indexs[j], 1))
        else:
            output.write("%s,%d\n" % (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次训练:

log1.bmp-2831.4kB

第2次训练:

log2.bmp-2657.9kB

第3次训练:

log3.bmp-2662kB

posted on 2016-06-07 13:39  linyihan  阅读(680)  评论(0编辑  收藏  举报

导航