libsvm 学习笔记

libsvm中tools 中提供了一个一条龙式的程序 easy.py

出于兴趣对原码做了一些学习

if len(sys.argv) <= 1:
	print('Usage: {0} training_file [testing_file]'.format(sys.argv[0]))
	raise SystemExit

(1)sys.argv: 实现从程序外部向程序传递参数,实质是个list

sys.argv[0]  -->  py程序本身

(2)raise SystemExit --> 退出程序

也可以用下面的格式

raise SystemExit('......')

(3) .format  用于字符串的格式化。 

{0}  即代表着sys.argv[0]会出现在{0}的位置上。这里理应就是easy.py

除了通过位置,还可以通过关键字或者字典进行映射。此外,.format还可以实现左右对齐,精度进制控制等

这种映射方式相对之前类C的%f方式有何优势?

大概是这样: 

print('{0},{1},{0},{0}'.format('wyz','21')
映射看起来要灵活得多

小结:这一段是对参数个数的检查,如果参数个数只有一个,即只有 python easy.py ,就提示正确用法,并退出


is_win32 = (sys.platform == 'win32')
if not is_win32:
	svmscale_exe = "../svm-scale"
	svmtrain_exe = "../svm-train"
	svmpredict_exe = "../svm-predict"
	grid_py = "./grid.py"
	gnuplot_exe = "/usr/bin/gnuplot"
else:
        # example for windows
	svmscale_exe = r"..\windows\svm-scale.exe"
	svmtrain_exe = r"..\windows\svm-train.exe"
	svmpredict_exe = r"..\windows\svm-predict.exe"
	gnuplot_exe = r"c:\tmp\gnuplot\binary\pgnuplot.exe"
	grid_py = r".\grid.py"

(1) sys.platform 返回操作系统名称,windows平台返回值是'win32'

(2)  ./表示同级文件, ../表示上级文件,这里定义了几个执行文件的路径


assert os.path.exists(svmscale_exe),"svm-scale executable not found"
assert os.path.exists(svmtrain_exe),"svm-train executable not found"
assert os.path.exists(svmpredict_exe),"svm-predict executable not found"
assert os.path.exists(gnuplot_exe),"gnuplot executable not found"
assert os.path.exists(grid_py),"grid.py not found"

train_pathname = sys.argv[1]
assert os.path.exists(train_pathname),"training file not found"
file_name = os.path.split(train_pathname)[1]
scaled_file = file_name + ".scale"
model_file = file_name + ".model"
range_file = file_name + ".range"

(1) os.path.exists()函数用来检验给出的路径是否真地存在

(2) assert 断言函数 用法

assert expression [, arguments]
如果expression 为假,就会输出后面这一句

(3) sys.argv[1] --> 等待training 的data集


if len(sys.argv) > 2:
	test_pathname = sys.argv[2]
	file_name = os.path.split(test_pathname)[1]
	assert os.path.exists(test_pathname),"testing file not found"
	scaled_test_file = file_name + ".scale"
	predict_test_file = file_name + ".predict"

这一段检查参数是否包含测试文件名


cmd = '{0} -s "{1}" "{2}" > "{3}"'.format(svmscale_exe, range_file, train_pathname, scaled_file)
print('Scaling training data...')
Popen(cmd, shell = True, stdout = PIPE).communicate()	

cmd = '{0} -svmtrain "{1}" -gnuplot "{2}" "{3}"'.format(grid_py, svmtrain_exe, gnuplot_exe, scaled_file)
print('Cross validation...')
f = Popen(cmd, shell = True, stdout = PIPE).stdout

这一段是最为难懂的

(1)cmd定义了一个字符串  svmscale_exe -s "range_file" "train_pathname" > "scaled_file"

(2)Popen 是subprocess模块中定义的一个类

实际创建了一个子进程。其中shell=True, 而 args 是字符串,它将作为命令行字符串通过shell 执行。

Popen的communicate方法使父进程与子进程能够交流,二元组 (stdoutdata, stderrdata) 分别表示从标准出和标准错误中读出的数据。

而设置stdout = Pipe ,则使得父进程可以接受子进程返回的数据。communicate会阻塞父进程直至子进程结束。

详细参见Baby_Ape的博客 非常详细易懂

小结而言,这段代码首先创建子进程scale训练集;然后创建子进程利用grid.py和gnuplot来寻找最好的svm参数

line = ''
while True:
	last_line = line
	line = f.readline()
	if not line: break
c,g,rate = map(float,last_line.split())

看起来f是grid.py 输出的文件。 c,g 是SVM的参数,rate则是结果

(1)readline() 方法用于从文件读取整行,包括 "\n" 字符  用法:fileObject.readline();

(2)if not line:break 读到空行就退出

(3).split 分隔符默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等。  用法: str.split(str="", num=string.count(str))

num为分割次数

(4)map函数,将分割出的内容都变为float,然后赋给c,g,rate。处在float位置的通常是某个函数


print('Best c={0}, g={1} CV rate={2}'.format(c,g,rate))

cmd = '{0} -c {1} -g {2} "{3}" "{4}"'.format(svmtrain_exe,c,g,scaled_file,model_file)
print('Training...')
Popen(cmd, shell = True, stdout = PIPE).communicate()

print('Output model: {0}'.format(model_file))

利用最好的参数对训练集再次进行训练


if len(sys.argv) > 2:
	cmd = '{0} -r "{1}" "{2}" > "{3}"'.format(svmscale_exe, range_file, test_pathname, scaled_test_file)
	print('Scaling testing data...')
	Popen(cmd, shell = True, stdout = PIPE).communicate()	

	cmd = '{0} "{1}" "{2}" "{3}"'.format(svmpredict_exe, scaled_test_file, model_file, predict_test_file)
	print('Testing...')
	Popen(cmd, shell = True).communicate()	

	print('Output prediction: {0}'.format(predict_test_file))

如果有测试集,利用最优参数对测试集进行预测


总结: easy.py (1)参数,文件路径等进行检查

                        (2)建立子进程scale数据,利用grid.py找到最优参数

                        (3)利用最优参数跑训练集和测试集,并输出结果


你可能感兴趣的:(Python)