在上一篇文章讲解libsvm的python版入门实例时,遇到一个遗留问题,就是不能用官网给的API保存训练好的模型文件。总是提示,问题定位到svmutil的svm_save_model方法。
libsvm.svm_save_model(model_file_name, model)
ctypes.ArgumentError: argument 1:: wrong type
刚开始一直找不到原因,后来偶然一次在服务器(服务器python环境2.6,本机python环境3.2)上跑时,忘记注释掉savemodel这句,最后居然生成了model文件,才发现原来这个是libsvm3.11的一个bug,也是因为python3不向前兼容引起的问题。经过跟libsvm的作者Prof. Lin及其学生交流后发现这个问题。
I am writing to you for the problem I found in the python interface of LIBSVM.I am using the version 3.11,I found that if I run the program under the environment of python 3.2,it crashes.However,in the environment of python2.5,it does well.
I used the python files including svm.py and svmutil.py downloading from your site.When I want to save the model file that has been trained.But it crashed .It says “ctypes.ArgumentError: argument 1:
: wrong type .” in the file “..\libsvm\libsvm-3.11\python\svmutil.py” ,line 45 ,in the method named “svm_save_model”. The following codes are how I called the interface.……
model = svmutil.svm_train(prob ,’-h 0′)
model_file_name = ‘test.model’svmutil.svm_save_model(model_file_name, model)
……
However it does well when I change the environment to python 2.5.
最后给出的解决方案是:
修改文件svmutil.py.
将32行的model = libsvm.svm_load_model(model_file_name)修改成model = libsvm.svm_load_model(model_file_name.encode())
45行的libsvm.svm_save_model(model_file_name, model)修改成libsvm.svm_save_model(model_file_name.encode(), model)
估计下个版本libsvm3.13?会fix这个问题。
原因是在python3中使用了新类型bytes,用来表示二进制数据和编码文本,str和bytes不能混合,需要时,必须进行显示的转换,转换方法是str.encode()(str->bytes)和bytes.decode()(bytes->str).官网说法猛击这里。以前的strings变成了unicode,在libsvm的C/C++实现中用的char*(DLL里面的),就不兼容了。所以总提示参数错误。
附上libsvm的入门实例(115网盘网络紧张好像提取不了,iask居然慢慢审核,只有放在自己空间了)(压缩包解压密码:www.tanglei.name)