此文件通过调用LIBSVM工具包中的相关可执行文件进行SVM的训练、测试和网格生成。
1.引入相关的头文件
2.命令行参数检查
3.可执行文件路径的设置
其中, svmscale_exe:svm-scale可执行文件路径
svmtrain_exe:svm-train可执行文件路径
svmpredict_exe:svm-predict可执行文件路径
grid_py:grid.py脚本路径,用于生成网格
gnuplot_exe:gnuplot可执行文件路径,用于绘制图表
注意:路径要根据自己系统中文件所在的路径来配置
详细解析一下这句代码:svmscale_exe = r"..\windows\svm-scale.exe"
这行代码定义了一个字符串变量 svmscale_exe
,其值为 r"..\windows\svm-scale.exe"
,这是一个包含了原始字符串字面值的 Python 字符串。
让我逐步解释这个字符串的含义:
-
r"..\windows\svm-scale.exe"
是一个原始字符串字面值(raw string literal),在 Python 中使用r
前缀,原始字符串不会对反斜杠进行转义。这在处理文件路径时很有用,因为文件路径通常包含反斜杠。 -
..\windows\svm-scale.exe
表示一个文件路径,其中..
表示返回上一级目录,然后\windows\svm-scale.exe
是相对于上一级目录的路径。这样的路径通常用于指定某个文件或可执行程序的位置。
因此,svmscale_exe
变量包含了指向 svm-scale.exe
可执行文件的路径。这种方式的使用通常用于在程序中引用外部工具或文件的路径,以便程序能够准确地定位和使用,svmscale_exe
变量可能用于构建包含执行 svm-scale.exe
命令的字符串。
这样,脚本就根据操作系统类型设置了LIBSVM工具包中相关文件的路径,以便后续的调用
4.assert语句检查文件是否存在
一系列assert
语句用于检查相关可执行文件和脚本是否存在。如果某个文件不存在,assert
语句将抛出AssertionError
,中断程序的执行。
例如,assert os.path.exists(svmscale_exe),"svm-scale executable not found"
检查 svm-scale 可执行文件是否存在。如果不存在,将抛出 AssertionError,并显示错误消息 “svm-scale executable not found”。这是为了确保在继续执行脚本之前,必须存在 svm-scale 可执行文件。
5.构建文件名
在Python中,sys.argv 是一个用于访问命令行参数的列表,它是sys模块中的一个变量。具体来说,sys.argv 包含了从命令行传递给Python脚本的所有参数。
其中,sys.argv[0] 表示脚本的名称(或者是运行的 Python 解释器的路径)
sys.argv[1] 到 sys.argv[n] 包含传递给脚本的命令行参数,其中 n 是参数的数量
也就是说,这个列表的第一个元素是脚本的名称,随后的元素是在运行脚本时传递给它的命令行参数。
例如,如果在命令行中运行脚本 script.py 并传递了一些参数,可以通过 sys.argv 获取这些参数。假设运行命令:python script.py arg1 arg2 arg3
那么在script.py 中,sys.argv 将是一个包含以下内容的列表:['script.py', 'arg1', 'arg2', 'arg3']
可以通过索引访问这些参数,例如 sys.argv[1] 获取第一个参数 'arg1'
6. 使用Python中的subprocess模块执行命令行命令
这段代码是使用 Python 中的 subprocess
模块来执行命令行命令。让我逐步解释每个部分:
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}
,{1}
,{2}
,{3}
分别由svmscale_exe
,range_file
,train_pathname
,scaled_file
替代。这个字符串构建了一个命令,该命令调用了可执行文件svmscale_exe
,传递了一些参数,然后将输出重定向到文件scaled_file
中。 -
print('Scaling training data...')
这一行简单地打印一条消息,指示正在进行训练数据的缩放操作。 -
Popen(cmd, shell=True, stdout=PIPE).communicate()
这一行使用subprocess.Popen
执行了前面构建的命令。这个命令通过shell=True
参数告诉系统使用 shell 来执行命令,stdout=PIPE
则是将命令的标准输出捕获起来,以便后续调用communicate()
方法获取输出。但是,这里的命令中使用了>
符号,表示将标准输出重定向到文件,因此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
-
cmd
这一行构建了一个命令字符串,其中{0}
,{1}
,{2}
,{3}
分别由grid_py
,svmtrain_exe
,gnuplot_exe
,scaled_file
替代。这个命令涉及支持向量机的训练和交叉验证。 -
print('Cross validation...')
这一行打印一条消息,指示正在进行交叉验证操作。 -
Popen(cmd, shell=True, stdout=PIPE).stdout
这一行执行了前面构建的命令,同样使用了stdout=PIPE
来捕获命令的标准输出。值得注意的是,这里的.stdout
属性获取了标准输出流,但没有使用communicate()
方法,因此标准输出并没有被捕获到。如果你需要获取输出,可能需要使用communicate()
方法,并在其中处理输出数据。
line = ''
while True:
last_line = line
line = f.readline()
if not line: break
c,g,rate = map(float,last_line.split())
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))
这段代码的作用是读取文件中的数据,找到最后一行的数据,然后使用这些数据构造一个命令并执行该命令。
具体来说,代码首先定义了一个空字符串line
,然后进入一个无限循环。在循环中,每次都会将上一行的内容赋值给last_line
,然后读取下一行的内容赋值给line
。如果读取到的内容为空(即已经读取到文件末尾),则跳出循环。
接着,代码将最后一行的内容使用split()
方法按空格分割,并将结果映射为浮点数类型,分别赋值给c
、g
和rate
三个变量。
然后,代码使用这些数据构造了一个命令cmd
,并使用Popen
模块的communicate()
方法执行该命令。该命令的具体内容是调用svmtrain_exe
程序,传入参数-c
、-g
、scaled_file
和model_file
。
最后,代码输出了训练的相关信息,包括最佳的c
、g
值以及交叉验证的准确率rate
,以及输出模型的文件名model_file
。
需要注意的是,代码中使用了Popen
模块执行命令,这意味着该命令是在操作系统的命令行中执行的,而不是在Python解释器中执行的。
7. 读取命令行参数进行缩放(scaling)和预测
通过读取命令行参数来执行一系列操作,主要是对测试数据进行缩放(scaling)和使用已经训练好的模型进行预测。
首先,代码检查命令行参数的数量是否大于2,如果是的话,说明有足够的参数传递给脚本。接下来,它构建两个命令并执行它们。
-
缩放测试数据:
- 使用
svmscale_exe
执行缩放命令。构建的命令是'{0} -r "{1}" "{2}" > "{3}"'
,其中:{0}
是svmscale_exe
,表示执行缩放的可执行文件。-r "{1}"
表示使用指定的范围文件(range_file
)进行缩放。"{2}"
是测试数据的路径。> "{3}"
表示将缩放后的数据输出到指定的文件scaled_test_file
。
- 执行缩放命令,并将标准输出重定向到管道(
stdout = PIPE
)。
- 使用
-
使用训练好的模型进行预测:
- 使用
svmpredict_exe
执行预测命令。构建的命令是'{0} "{1}" "{2}" "{3}"'
,其中:{0}
是svmpredict_exe
,表示执行预测的可执行文件。"{1}"
是缩放后的测试数据文件。"{2}"
是之前训练好的模型文件。"{3}"
是输出的预测结果文件。
- 执行预测命令,不重定向标准输出。
- 使用
最后,代码输出一些信息,包括缩放测试数据、进行预测,并输出预测结果的文件名。需要注意的是,这里使用了命令行的重定向符号 >
将命令的输出写入文件。
什么是原始字符串字面值
-
原始字符串字面值是在Python中表示字符串的一种方式,使用前缀
r
或R
。与普通字符串不同,原始字符串中的反斜杠字符(\
)不会被解释为转义字符。这意味着在原始字符串中,反斜杠后面的字符被视为普通字符,而不是转义序列。例如,考虑以下两个字符串:
normal_string = "This is a \n newline character."
raw_string = r"This is a \n newline character."
-
在
normal_string
中,\n
被解释为换行字符,而在raw_string
中,\n
被当作两个普通字符:反斜杠和字母’n’。因此,原始字符串不会对反斜杠进行转义处理。原始字符串通常用于处理文件路径、正则表达式模式等场景。