在中国大学MOOC上看了胡浩基的机器学习课程,完全面向入门人群感觉挺好。其中有关原理的部分讲的很细。(虽然有几个细节我还是没懂.......)其中在第二章的例题兵王问题中课程只给了MATLAB的版本。但是,我相信也有极小部分人和我一样对MATLAB不太熟悉的。所以,我自己就按照我对老师的MATLAB的代码的理解写了python版本。先放源码大多数的内容我都会写在注释(中文)上,还有几个我认为大家可能会有疑惑的地方会在之后列出。

# -*- coding: utf-8 -*-import numpy as np
from libsvm.python.svm import *
from libsvm.python.svmutil import *def data_read_mat(file_name):'''从文件中取出数据:param file_name: 文件名称:return: 返回一个n*7的矩阵,前6项是三个坐标,第七项是标签'''num_list = []'''一下是对数据进行读入并且处理,其中open的参数中encoding之所以设置成UTF-8-sig是因为如果我们把这个参数设置为UTF-8或者不设置,在读入的开头多出\ufeff这么一串东西,有时候会以中文字的形式出现。'''with open(file_name,"r",encoding='UTF-8-sig') as file:for l in file:l = l.split(',')list_k = []for j in range(3):list_k.append(ord(l[j*2]) - ord('a'))list_k.append(ord(l[j*2 + 1]) - ord('0'))if(l[6][0] == 'd'):list_k.append(-1)else:list_k.append(1)num_list.append(list_k)num_mat = np.array(num_list,dtype="float")'''在此处是以numpy的二维数据矩阵的形式存储的,本以为使用numpy的数据进行运算可以使得训练的速度快一些。结果发现如果要往libsvm中的函数传入参数只能传入list型不能传入numpy的数据类型。所以,后面又把数据类型转回了list型。但是,我猜应该是有方法可以把numpy的数据类型传入使用的。于是我在读取数据后任然返回的是numpy的形式。'''return num_mat
def data_deal(mat,len_train,len1,len_test,len2):'''将数据进行处理,分出训练数据和测试数据:param mat: 大矩阵,其中包括训练数据和测试数据:param len_train:训练数据:param len1: 输入坐标:param len_test: 测试数据:param len2: 标签:return: 返回的依次是训练输入数据,测试输入数据,训练输入数据的标签,测试输入数据的标签'''np.random.shuffle(mat)  #先将矩阵按行打乱。然后根据要求对矩阵进行分割,第一部分就是训练集,第二部分就是测试集x_part1 = mat[0:len_train,0:len1]x_part2 = mat[len_train:,0:len1]y_part1 = mat[0:len_train,len1]y_part2 = mat[len_train:,len1]# 标准化# 根据训练集求出均值和方差avgX = np.mean(x_part1)stdX = np.std(x_part1)# print(avgX,stdX)#将训练集和测试集都进行归一化处理for data in x_part1:for j in range(len(data)):data[j] = (data[j] - avgX) / stdXfor data in x_part2:for j in range(len(data)):data[j] = (data[j] - avgX) / stdXreturn x_part1,y_part1,x_part2,y_part2
def TrainModel(CScale,gammaScale,prob):''':param CScale: 参数C的取值序列:param gammaScale:  参数γ的取值序列:param prob: 训练集合对应的标签:return: maxACC(最高正确率),maxACC_C(最优参数C),maxACC_gamma(最优参数γ)'''maxACC = 0maxACC_C = 0maxACC_gamma = 0for C in CScale:C_ = pow(2, C)for gamma in gammaScale:gamma_ = pow(2, gamma)# 设置训练的参数# 其中-v 5表示的是2折交叉验证# “-q”可以去掉这样也就可以看到训练过程param = svm_parameter('-t 2 -c ' + str(C_) + ' -g ' + str(gamma_) + ' -v 5 -q')ACC = svm_train(prob, param)  # 进行训练,但是传回的不是训练模型而是5折交叉验证的准确率#更新数据if (ACC > maxACC):maxACC = ACCmaxACC_C = CmaxACC_gamma = gammareturn maxACC,maxACC_C,maxACC_gamma
def getNewList(L,U,step):l = []while(L < U):l.append(L)L += stepreturn l
def TrainModelSVM(data,label,iter,model_file):'''模型训练并保存:param data: 数据:param label: 标签:param iter:训练次数,在原先的MATLAB代码中的次数是两次:param model_file:模型的保存位置:return: 返回最优参数'''#将数据转换成list型的数据。因为,在svm的函数中好像只能传入list型的数据进行训练使用X = data.tolist()Y = label.tolist()CScale = [-5, -3, -1, 1, 3, 5,7,9,11,13,15]  #参数C的2^CgammaScale = [-15,-13,-11,-9,-7,-5,-3,-1,1,3] #参数γ的取值2^γcnt = iterstep = 2 #用于重新生成CScale和gammaScale序列maxACC = 0 #训练过程中的最大正确率bestACC_C = 0 #训练过程中的最优参数CbestACC_gamma = 0 #训练过程中的最优参数γprob = svm_problem(Y, X)  # 传入数据while(cnt):#用传入的参数序列进行训练,返回的是此次训练的最高正确率,最优参数C,最优参数γmaxACC_train,maxACC_C_train,maxACC_gamma_train = TrainModel(CScale,gammaScale,prob)#数据更新if(maxACC_train > maxACC):maxACC = maxACC_trainbestACC_C = maxACC_C_trainbestACC_gamma = maxACC_gamma_train#根据返回的参数重新生成CScale序列和gammaScale序列用于再次训练,下一次训练的C参数和γ参数的精度会比之前更高#step就是CScale序列和gammaScale序列的相邻两个数之间的间隔new_step = step*2/10CScale = getNewList(maxACC_C_train - step,maxACC_C_train + step + new_step,new_step)gammaScale = getNewList(maxACC_gamma_train - step,maxACC_gamma_train + step + new_step,new_step)cnt -= 1#获得最优参数后计算出对应的C和γ,并且训练获得“最优模型”C = pow(2,bestACC_C)gamma = pow(2,bestACC_gamma)param = svm_parameter('-t 2 -c ' + str(C) + ' -g ' + str(gamma))model = svm_train(prob, param)  # 交叉验证准确率svm_save_model(model_file, model) #保存模型return model
def main():data_file = r"E:\python_study\KingSVM\krkopt.data"  #数据存放的位置(需要修改)mode_file = r"E:\python_study\KingSVM\model_file"   #训练模型保存的位置(需要修改)data_mat = data_read_mat(data_file)  #从文件中读取数据并处理#以下是对数据训练进行分配,可以根据你的需要进行调整train = 5000   #5000组数据作为训练数据test  = len(data_mat) - 5000  #剩下的数据作为测试数据#————————————————————————————————————————————————————————————#x_len = 6   #输入数据的维度是6维,即三个棋子的坐标y_len = len(data_mat[0]) - x_len  #输出的数据时1维,即两种结果iter = 2# 训练的次数,训练的次数越多参数就调整的精度就越高x_train,y_train,x_test,y_test = data_deal(data_mat,train,x_len,test,y_len) #对数据进行分割if (input("是否需要进行训练?") == 'y'):  #如果输入y就会进行训练,否则就可以直接使用之前训练的完成的模型model = TrainModelSVM(x_train,y_train,iter,mode_file)  #传入输入数据,标签进行模型的训练else:model = svm_load_model(mode_file)  #直接加载现有模型X = x_test.tolist() #将测试集的输入集转换成listY = y_test.tolist() #将测试集的输出集转换成listprint(Y[:10])p_labs,p_acc,p_vals = svm_predict(Y,X,model)if __name__ == "__main__":main()

最后,我在尝试后预测正确率比课程视频中放出来的低0.2%。但是,总体来说应该是没有问题。接下来是列举出我认为大家可能会碰到的问题。

1.在python中怎么安装libsvm?

我用的pycharm我猜用这种方式应该是可以安装的,具体细节百度一下。(虽然我没试过)

而我使用的安装方式是参照这个博客:python libsvm安装_jessica218的博客-CSDN博客

2.大家在百度libsvm的使用时,可能会看到这个函数svm.SCV。我在刚开始的时候也碰到了不少文章中使用这个的。但是,用了这个函数死活不行。我猜可能在libsvm的老版本中使用的就是这个,对应现在这个版本中svm.svm_train。除此之外的还有svmutil.svm_read_problem在现在的版本中好像也没有了。

3.为什么libsvm中参数传入不支持numpy的一些数据类型?

在svm.py文件中我们可以看到这样一段:

class svm_problem(Structure):_names = ["l", "y", "x"]_types = [c_int, POINTER(c_double), POINTER(POINTER(svm_node))]_fields_ = genFields(_names, _types)def __init__(self, y, x, isKernel=False):if (not isinstance(y, (list, tuple))) and (not (scipy and isinstance(y, scipy.ndarray))):raise TypeError("type of y: {0} is not supported!".format(type(y)))if isinstance(x, (list, tuple)):if len(y) != len(x):raise ValueError("len(y) != len(x)")elif scipy != None and isinstance(x, (scipy.ndarray, sparse.spmatrix)):if len(y) != x.shape[0]:raise ValueError("len(y) != len(x)")if isinstance(x, scipy.ndarray):x = scipy.ascontiguousarray(x) # enforce row-majorif isinstance(x, sparse.spmatrix):x = x.tocsr()passelse:raise TypeError("type of x: {0} is not supported!".format(type(x)))self.l = l = len(y)max_idx = 0x_space = self.x_space = []if scipy != None and isinstance(x, sparse.csr_matrix):csr_to_problem(x, self, isKernel)max_idx = x.shape[1]else:for i, xi in enumerate(x):tmp_xi, tmp_idx = gen_svm_nodearray(xi,isKernel=isKernel)x_space += [tmp_xi]max_idx = max(max_idx, tmp_idx)self.n = max_idxself.y = (c_double * l)()if scipy != None and isinstance(y, scipy.ndarray):scipy.ctypeslib.as_array(self.y, (self.l,))[:] = yelse:for i, yi in enumerate(y): self.y[i] = yiself.x = (POINTER(svm_node) * l)()if scipy != None and isinstance(x, sparse.csr_matrix):base = addressof(self.x_space.ctypes.data_as(POINTER(svm_node))[0])x_ptr = cast(self.x, POINTER(c_uint64))x_ptr = scipy.ctypeslib.as_array(x_ptr,(self.l,))x_ptr[:] = self.rowptr[:-1]*sizeof(svm_node)+baseelse:for i, xi in enumerate(self.x_space): self.x[i] = xi

其中注意这部分:

其中isinstance(a,type)是判断a是否是type类型的,我们看上图的第一行和第三行可以看到传入的参数x,y必须是list或者typle类型的,否则就会异常退出。

4.标准化这个步骤很重要法,如果没有标准化正确率就会变成大约90%。(瞎猜的正确率也是90%)

——————————————————————END————————————————————————

回答评论区river_ocean111的提问,因为来看这篇的基本上都是初学者,所以我想别人应该也会有这个问题。

在看完MOOC胡浩基的课后应该能明白下面这几点:

1.gamma是高斯核中所需要设置的超参数(在这个例子中使用的就是高斯核函数)(第二章第11个视频5:02)

至于具体细节我也不知道这个高斯核是怎么推导出来的,这个还需要看一些相关的资料。(就连李航的《统计学方法》中都没有详细阐述这个高斯核的由来,可见这个东西要么很基础要么很古老。)

2.C是SVM算法中所需要设置的一个超参数(第二章第4个视频2:50)

而这个的话直接看视频应该就能很好的理解为什么会有C这个超参数。

3.C,gamma由于人工经验所以选取的范围。C = 2^(-5)~2^(15),gamma=2^(-15)~2^(3)(第二章第12个视频6:59)

明白了之后在回到coding这,你可以这样理解。我们的目的是需要找到一个最优的C和gamma。当然在这个问题中我们都当做C和gamma都大致符合下面这个图,就只是一座山的形状,而我们要找的是那个山尖。

(没有3D的绘图工具只能画个2D的来凑合一下)

而事实是大致符合下面这个图,像一个丘陵一样。我们想要找到的是最好全局的最高点,但是这是非常困难的所以我们只需要找到一个全局的较高点即可。

如果你到此为止都看懂了,那你应该也就能理解了其实也不一定非要用pow(2,C),pow(2,gamma),完全可以把111行和112行CScale,gammaScale之后的列表改成具体的数值。这样一来直接用C和gamma就行。(我没有试过,我估计单次训练的速度会变快。但是,每次训练的效果会变差。)

回答第二个问题:我试了一下什么也不用改。至于具体原因的话,还是琢磨一下SVM的源码吧,这个我也没有仔细研究过。从SVM的原理上来看的话,咋们也可以知道SVM就是单纯的解决2分类问题与分类标签为1,0还是标签为1,-1并没有关系。

中国大学MOOC胡浩基的机器学习第二章(支持向量机)兵王问题python版本——在python上初步使用libsvm相关推荐

  1. python语言程序设计是什么课文_中国大学MOOC有哪些优质课程?

    说到学习,相信很多人囤了一堆自学网站吧?囤完之后,是不是依然不知道要学什么? 因为免费的网络课程,质量参差不齐,试错成本太高. 所以小叶子帮大家做了这样一件事,直接帮你从中国大学MOOC里挑选了25门 ...

  2. 新农慕课python答案、第七周_中国大学MOOC(慕课)_Python机器学习应用_章节答案期末答案...

    中国大学MOOC: 我国GDP增速在全球各经济体中处于中高速状态.这样,中国章节收入因素并没有对中国的消费产生极大的向下的约束,中国章节因此居民收入因素不是影响消费增速的因素. 经过文艺复兴和教育的世 ...

  3. 【Unity入门教程】 第八章 人工智能【中国大学MOOC游戏引擎原理及应用】

    以下均为来自中国大学mooc 游戏引擎原理及应用时的学习笔记,不含商用,仅供学习交流使用,如果侵权请联系作者删除. 文章目录 8.1 自动寻路 8.2 巡逻 8.3 视野 8.4 自动攻击 8.5 追 ...

  4. 【神经网络与深度学习-TensorFlow实践】-中国大学MOOC课程(八)(TensorFlow基础))

    [神经网络与深度学习-TensorFlow实践]-中国大学MOOC课程(八)(TensorFlow基础)) 8 TensorFlow基础 8.1 TensorFlow2.0特性 8.1.1 Tenso ...

  5. 中国大学 MOOC 课程Python语言程序设计 (第11期)测试答案(1-5周)

    中国大学 MOOC 课程Python语言程序设计 (第11期)测试答案(1-5周)  Lan   2020-05-03 14:21   369 人阅读  0 条评论 感谢中国大学MOOC提供的学习平台 ...

  6. 100行matlab,中国大学MOOC: Matlab中可以产生100行100列元素全是1的正确的命令是() 答案:ones(100)...

    中国大学MOOC口所有之电力备皆由流电动机俪之.俟:误 一节若为字头.字头.字腹.字尾四分,吐字归音之迹常可分为出字.立者.归音三也,出字要力,立者将引,归音将位.俟:贾 中国大学MOOC乘高羊场利之 ...

  7. 【神经网络与深度学习-TensorFlow实践】-中国大学MOOC课程(四)(Python语言基础(2))

    [神经网络与深度学习-TensorFlow实践]-中国大学MOOC课程(四)(Python语言基础(2)) 第4讲 Python语言基础(2) 4.1 内置数据结构 4.1.1 序列数据结构(sequ ...

  8. 【神经网络与深度学习-TensorFlow实践】-中国大学MOOC课程(十四)(卷积神经网络))

    [神经网络与深度学习-TensorFlow实践]-中国大学MOOC课程(十四)(卷积神经网络)) 14 卷积神经网络 14.1 深度学习基础 14.1.1 深度学习的基本思想 14.1.2 深度学习三 ...

  9. 下列属于PHP的数据类型的是,中国大学MOOC: 下列不属于PHP数据类型的是( )。...

    中国大学MOOC: 下列不属于PHP数据类型的是( ). 答:double 中国大学MOOC: 下列哪个选项不是学生不敢或不愿表达自己的想法的原因? 答:说话的人太多了,学生没有机会表达自己的观点 以 ...

最新文章

  1. 关闭aslr oracle,地址空间布局随机化 (Address Space Layout Randomization, ASLR)
  2. java 逻辑或 作用_Java开发中与之间的区别,你真的知道吗?
  3. 使用蓝图构建Flask项目目录
  4. 解决ASP.NET MVC(post数据)Json请求太大,无法反序列化,而报【远程服务器返回错误: (500) 内部服务器错误】...
  5. babel css3新特性_css3 transform属性多值的顺序问题
  6. P2966 [USACO09DEC]牛收费路径Cow Toll Paths
  7. cocos2d-x 3.1.1 学习笔记[21]cocos2d-x 创建过程
  8. Anaconda下载与安装详解
  9. open3d 0.13的c++版本使用demo
  10. java编程填空及答案_JAVA填空题标准答案(103题)
  11. Proxy ARP--即ARP代理
  12. JavaScript 是如何工作的:模块的构建以及对应的打包工具
  13. 计算机网络——基于IP多播的网络会议程序
  14. windows设置某应用开机自启
  15. 基于Wireshark的IP数据包头中ToS段介绍2-1
  16. 当Proteus 8 Professional打开出现:已使用符号sMKRORIGIN但未在库中找到.
  17. wps插入visio流程图
  18. 执行计划管理 (SPM)
  19. 十六、MDT 2013 Update 1批量部署-应用程序导入及自动安装(含OFFICE 2007安装)
  20. esp8266对接天猫精灵(3)原理

热门文章

  1. P1717 Finger guessing
  2. 时间序列预测的评估指标补遗
  3. 前端技术的趋势和最新的发展
  4. 《时间从来不语,却回答了所有问题》读后感
  5. 设计模式七大设计原则
  6. 什么是爱情——碧海青天BBS
  7. iOS safeAreaInsets安全区域相关知识
  8. 蓝海彤翔执行副总裁张加廷接受【联播苏州】独家专访
  9. DDR3的学习笔记(一)
  10. Python实现手写数字的识别