Hom's Blog


SVMlight

SVMlight Multiclass

数据预处理

Traing数据SVMlight multiclass的输入格式:

<line> .=. <target> <feature>:<value> <feature>:<value> ... <feature>:<value> # <info>
<target> .=. <integer>
<feature> .=. <integer>
<value> .=. <float>
<info> .=. <string>

3 1:0.43 3:0.12 9284:0.2 # abcdef

第一行可以是注释,使用#在开头. 其余每行都是数据.
target是类的值(需要大于0),feature/value对是对应每个feature的值,feature是某个数值来代替和区分.

Excel预处理

Excel主要用来做数据最初步的放置, 整理好后全部复制再黏贴到文本文档成为一份data即可.随后就可以进行后续处理或者直接SVM了.

  • 对齐数据: 例如根据某些ID, 将类ID和feature对上.
    =INDEX(Sheet2!C$2:C$636,MATCH($B6,Sheet2!$I$2:$I$636,0)) 使用id进行match. match函数用来查找区域并返回查到到的值在第几项, 从而用该项获取刚行别的值(用index函数).
    这里, 当前表格储存了feature和对应的每行数据的ID($B6). sheet2里有ID(sheet2!I)及对应的类号(sheet2!C). 在当前表格的新列中使用该公式,将自动获取对应类号.

  • 构建数据列: 在新的数据列,复制原数据值并构建成SVM所需 feature:value 形式. 使用column函数计算所在列号: =COLUMN()-89&":"&AQ2
    其中,AQ2是值所在, COLUMN()-89是扣出feature编号.&连接字符串.89这里根据自己数据表格进行修改了,保证第一个feature是1就好了.

  • 构建不同的trainingset 和validationset: 新建一列,并全部赋值为=rand(), 然后根据双列(1.分类号, 2.随机数大小)来排序即可. 按比例抽取数值.
    这个过程最好借助VBA来实现, 在每次使用一次rand()函数和排序后,执行一次VBA脚本, 然后将数据复制到一个training和validation的sheet里, 再复制出来.
    使用VBA来进行优点是一套都在excel中进行,但缺点是麻烦..尤其要自己分好每类的数量..

下面的是个示例VBA处理数据.这里有点问题,因为SVM的1:10 的格式拿过去时会被作为时间格式进行处理…有待解决…

Sub CopyValue()

Sheet10.Range("A1:A999").Text = Sheet2.Range("C2:C1000").Value
Sheet10.Range("B1:CU999").Text = Sheet2.Range("CZ2:GS1000").Value

'class 1: 1-8 , 8
Sheet3.Range("A1:A6").Value = Sheet10.Range("A1:A6").Value
Sheet4.Range("A7:A8").Value = Sheet10.Range("A7:A8").Value

'class 2: 9-26 , 18
Sheet3.Range("A9:A22").Value = Sheet10.Range("A9:A22").Value
Sheet4.Range("A23:A26").Value = Sheet10.Range("A23:A26").Value

'class 3: 27-36 , 10
Sheet3.Range("A27:A34").Value = Sheet10.Range("A27:A34").Value
Sheet4.Range("A34:A36").Value = Sheet10.Range("A34:A36").Value

' Delete blank row
Sheet3.Range("a1:a" & Range("a65536").End(xlUp).Row).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
Sheet4.Range("a1:a" & Range("a65536").End(xlUp).Row).SpecialCells(xlCellTypeBlanks).EntireRow.Delete

End Sub

Python预处理

准备好数据后, 需要区分出一份training set和一份validation set, 这里使用下面的python脚本处理. 可以产生多套不同排序而产生的training set和validation set, 默认比例是近似4:1.

Python script to generate training sets and validation sets. User can assign the total output set number for many model and also the training set radio.
Use as: python SVM_trainvalid.py data.txt 20 0.8

在该脚本中对每一组training set和validation set有四套处理方法:(在method中设置):

  1. 乱序每类的数据,从头80%中作为training set, 后20%作为validation set.
  2. 每类数据中随机抽取数据,按总数80%作为training set. 该方法会和方法一差异为产生重复数据.但每类总数还是不变的.
  3. 从原数据中随机抽取数据,最后产生一定量数据的training set.保证了每类在training set中所有组的统计概率和原始数据相等.
  4. 先从所有类中随机抽取一类,再随机抽取一个数据.保证了每类在training set中所有组的统计概率相等.

这里使用到random模块的shuffle(列表乱序)和randint(一定数据中的随机数).
第一种方法适合简易地产生多套不同的training set和validation set, 每一套都产生一个训练的model. 保证抽取数据的均匀性.(每套只是分到T/V顺序不同)
第二种方法为导致每一套的数据差异增大, 每一套的model差异增大, 但多个model下来数据还是均匀的,每个model中每类数目比例也一致.(每套每类数据有差异,但每类总数一致)
第三种方法从总体数据中随机抽取,因此每一套数据的类的个数和每类的数据都差异更大,每个model差异更大.但多个model下来数据平均和原始数据一致.(每类的个数都产生差异)
第四种方法先随机一个类再随机一个数据,每套model差异大,但数据平均下来每类个数一致,每类中每个数据概率一致. 可以扰动原始数据的每类数据数据量不同. (每类总体下相同数目)

遇到的问题:

  1. 例如两类数据,只有两个特征,若两类数据个数相同,出现 “1:1 2:1” 时会默认判断到第一类.此时用方法1和方法2即使产生多个model,每个model都会判断到第一类,而不是50%概率.
  2. 通过扰动每套数据中每组数据的数量,但平均下每组数据数量(概率)均等(方法3当原始数据每类数据数量相同或者直接方法4),此时依然会有概率某套数据下类1数量=类2数量,此时出现概率为(1/(training set个数/2)),因此training set数量增大,此种误判概率减少.由于多套数据中每类数目不均等,判断1/2概率总体一致,对于”1:1 2:1” 会50%概率判断为第一类.
  3. 对于同样双特征双类概率问题,当原始数据中每类数据数量不等(例如1:3),用第三种方法出来的每套数据1和2比例约等于1:3.也就是第二类会多些,因此觉得第二类权重大.此时即使产生100个model,100个model对于”1:1 2:1”都是判断为第二类.此时要用方法4.
  4. 即使使用方法四,每个类对应相应feature, 当数据出现如 “1:2”这样,判断同样出现偏差.即如果特征值不等(训练集或者测试集),同样产生偏差,不能成功按概率分类.

小结: SVM根据feature和值能很好地进行分类, 但一个新对象具备多类特征时,想计算出每类相应权重就难点了.对训练数据均匀化有利于判断.

Matlab预处理

类似于python预处理,其实不过是换了不同函数和操作方式罢了.类似还可以用R进行预处理和分析.
利用randperm产生随机数列,这里50假设有50个数据.
根据随机数列的百分比数量的序号来选取数据.

Matlab做法:

A=load('data.txt');
B=randperm(50); 
Validation=A(B(1:10),:);
Training=A(B(11:50),:);

SVMlight Multiclass学习过程(learn)

svm_multiclass_learn -c 1.0 example_file model_file

SVMlight Multiclass分类过程(classfy)

svm_multiclass_classify [options] test_example_file model_file output_file

在训练时,先将数据分为一个training set和一个validation set, 使用trainging set进行svm_multiclass_learn产生相应的model.此时要使用一个相应的c. 随后使用training set和validation set使用该model进行预测分类(svm_multiclass_classify),输出时会根据本来设置的类值和预测的值进行错误率计算,(Zero/one-error一行是错误率).调整c值,使两个set的错误都尽可能小,c值也尽可能小. (c值越大错误判罚加大,判断越准,但也容易依赖于训练集). 以下bash脚本就是执行这个功能(配合之前的python脚本), 产生多套T/V set,对每套进行模型计算和测试,抓取错误率,测试不同c值(不输入第三参数时,否则只用一个c值),最后根据不同c值的错误率方便选c值.

#! /bin/bash
# Author: Hom 2015.8.18
# Use "python SVM_trainvalid.py data_file modelnum trainradio" to generate training and validation sets first.

if [ -z $1 ];then
	echo "No input data file is given!"
	exit;
fi
fpre=${1%.*}
fext=${1##*.}

setnum=$2
if [ -z $2 ];then
	setnum="1";
fi

cvallist=$3

if [ -z $3 ];then
	cvallist="1 50 100 150 200 300 400 500 700 1000";
fi

echo $1 > ${fpre}_out.log


for cval in $cvallist
do
for i in `seq $setnum`
do

./svm_multiclass_learn.exe -c $cval ${fpre}_train_${i}.${fext} ${fpre}_model_${i}_c${cval}.txt >/dev/null
echo -n ${fpre}_train_${i} $cval " : ">> ${fpre}_out.log
./svm_multiclass_classify.exe ${fpre}_train_${i}.${fext} ${fpre}_model_${i}_c${cval}.txt ${fpre}_train_${i}_out.txt |grep "Zero/one-error" >> ${fpre}_out.log
echo -n ${fpre}_valid_${i} $cval " : ">> ${fpre}_out.log
./svm_multiclass_classify.exe ${fpre}_valid_${i}.${fext} ${fpre}_model_${i}_c${cval}.txt ${fpre}_valid_${i}_out.txt |grep "Zero/one-error" >> ${fpre}_out.log

done
done

if [ -z $3 ];then
	rm -rf ${fpre}_model_*_c*.txt
	rm -rf ${fpre}_train_*_out.txt ${fpre}_valid_*_out.txt
fi

以下脚本专门用于产生多个model.

#! /bin/bash
# Author: Hom 2015.8.18
# Use "python SVM_trainvalid.py data_file modelnum trainradio" to generate training and validation sets first.
# Use "./svm_model.sh data_file modelnum cval" to generate many model.

if [ -z $1 ];then
	echo "No input data file is given!"
	exit;
fi
fpre=${1%.*}
fext=${1##*.}

setnum=$2
if [ -z $2 ];then
	setnum="1";
fi

cval=$3
if [ -z $3 ];then
	cval="1";
fi

for i in `seq $setnum`
do
./svm_multiclass_learn.exe -c $cval ${fpre}_train_${i}.${fext} ${fpre}_model_${i}.txt > /dev/null
done

以下脚本进行分类.

#! /bin/bash
# Author: Hom 2015.8.18
# Use "python SVM_trainvalid.py data_file modelnum trainradio" to generate training and validation sets first.
# Use "./svm_test.sh data_file test_file modelnum" to test with many models.

if [ -z $1 ];then
	echo "No input data file is given!"
	exit;
fi
fpre=${1%.*}
fext=${1##*.}

setnum=$3
if [ -z $3 ];then
	setnum="1";
fi

testf=$2
if [ -z $2 ];then
	echo "No input test file is given!"
	exit;
fi
tpre=${2%.*}
text=${2##*.}

echo $1 $2 > ${tpre}_testout.txt


for i in `seq $setnum`
do
echo -n ${fpre}_model_${i} " : ">> ${tpre}_testout.txt
./svm_multiclass_classify.exe $testf ${fpre}_model_${i}.txt ${tpre}_model_${i}_out.txt |grep "Zero/one-error" >> ${tpre}_testout.txt
done

以下脚本用于一次性产生100套不同T/V set,并训练及对test例子进行测试.最后抓取测试结果中错误的个数(注意是100套的结果这里).

#! /bin/bash

python SVM_trainvalid.py data.txt 100
./svm_model.sh data.txt 100 1
./svm_test.sh data.txt test.txt 100
grep "100.00%" test_testout.txt |wc -l

Reference

  1. excel把一列或多列数据随机打乱顺序排列排序
  2. SVMlight multiclass
  3. svmlight python
  4. Resource
  5. Ensembles of classifiers


◆ 本文地址: http://platinhom.github.io/2015/08/12/svmlight/, 转载请注明 ◆

前一篇: 能让你成为更优秀程序员的10个C语言资源(ZZ)
后一篇: Python调用Fortran


Contact: Hom / 已阅读()
Source 类别: MathStat  标签: Stat  MachineLearning  Python  Bash  Excel