支持向量机代码实践
理论部分:(72条消息) 支持向量机详细解释_better_than的博客-CSDN博客
代码:https://github.com/vistor985/-.git
数据集
标题:平衡秤重量和距离数据库
相关信息:
这个数据集是用来建立心理学模型的实验结果。每个例子都被归类为具有天平向右倾斜,向左倾斜,还是向左倾斜平衡。这些属性是左权重距离,合适的重量,合适的距离。的正确的查找类的方法是较大的(left-distance * left-weight)和(right-distance *)的重量)。如果它们相等,那就是平衡的。
1.实例数:625(49平衡,288左,288右)
2.属性数量:4(数字)+类名= 5
属性信息:
- 类名称:3 (L, B, R)
- 左权重:5 (1,2,3,4,5)
- 左距离:5 (1,2,3,4,5)
- 右权重:5(1、2、3、4、5)
- 右距离:5 (1,2,3,4,5)
类分布:
- 46.08%是L
- 07.84%的人是B
- 3.46.08%是R
修改:
为了方便用于二分类,我们选择将R和B改为1,L为0
加载数据集:
def loadCSVfile2():
from sklearn.model_selection import train_test_split
tmp = np.loadtxt("balance-scale.csv", dtype=str, delimiter=",")
for line in tmp:
if line[0] == 'L':
line[0] = 0
else:
line[0] = 1
data = tmp[1:, 1:].astype(float) # 加载数据部分
label = tmp[1:, 0].astype(float) # 加载类别标签部分
for i in range(len(label)):
if label[i] == 0:
label[i] = -1
# print(tmp)
x_train, x_test, y_train, y_test = train_test_split(data, label, test_size=0.2)
return x_train, x_test, y_train, y_test # 返回array类型的数据
算法类
仅用于记录重要的变量,方便代码编写即理解。
class optStruct:
def __init__(self, dataMatIn, classLabels, C, toler, kTup):
# 数据矩阵
self.X = dataMatIn
# 数据标签
self.labelMat = classLabels
# 松弛变量
self.C = C
# 容错率
self.tol = toler
# 矩阵的行数
self.m = np.shape(dataMatIn)[0]
# 根据矩阵行数初始化alphas矩阵,一个m行1列的全零列向量
self.alphas = np.mat(np.zeros((self.m, 1)))
# 初始化b参数为0
self.b = 0
# 根据矩阵行数初始化误差缓存矩阵,第一列为是否有效标志位,第二列为实际的误差E的值
self.eCache = np.mat(np.zeros((self.m, 2)))
# 初始化核K
self.K = np.mat(np.zeros((self.m, self.m)))
# 计算所有数据的核K
for i in range(self.m):
self.K[:, i] = kernelTrans(self.X, self.X[i, :], kTup)
SMO算法
以下是算法的核心代码
def smoP(dataMatIn, classLabels, C, toler, maxIter, kTup=('lin', 0)):
# 初始化数据结构
oS = optStruct(np.mat(dataMatIn), np.mat(classLabels).transpose(), C, toler, kTup)
# 初始化当前迭代次数
iter = 0
entrieSet = True
alphaPairsChanged = 0
# 遍历整个数据集alpha都没有更新或者超过最大迭代次数,则退出循环
while (iter < maxIter) and ((alphaPairsChanged > 0) or (entrieSet)):
alphaPairsChanged = 0
# 遍历整个数据集
if entrieSet:
for i in range(oS.m):
# 使用优化的SMO算法
alphaPairsChanged += innerL(i, oS)
print("全样本遍历:第%d次迭代 样本:%d, alpha优化次数:%d" % (iter, i, alphaPairsChanged))
iter += 1
# 遍历非边界值
else:
# 遍历不在边界0和C的alpha
nonBoundIs = np.nonzero((oS.alphas.A > 0) * (oS.alphas.A < C))[0]
for i in nonBoundIs:
alphaPairsChanged += innerL(i, oS)
print("非边界遍历:第%d次迭代 样本:%d, alpha优化次数:%d" % (iter, i, alphaPairsChanged))
iter += 1
# 遍历一次后改为非边界遍历
if entrieSet:
entrieSet = False
# 如果alpha没有更新,计算全样本遍历
elif (alphaPairsChanged == 0):
entrieSet = True
print("迭代次数:%d" % iter)
# 返回SMO算法计算的b和alphas
return oS.b, oS.alphas
训练及测试
def testRbf(k1=1.3):
# 加载训练集
dataArr, testDataArr, labelArr, testLabelArr = loadCSVfile2()
# 根据训练集计算b, alphas
b, alphas = smoP(dataArr, labelArr, 200, 0.0001, 100, ('rbf', k1))
datMat = np.mat(dataArr)
labelMat = np.mat(labelArr).transpose()
# 获得支持向量
svInd = np.nonzero(alphas.A > 0)[0]
sVs = datMat[svInd]
labelSV = labelMat[svInd]
print("支持向量个数:%d" % np.shape(sVs)[0])
m, n = np.shape(datMat)
errorCount = 0
for i in range(m):
# 计算各个点的核
kernelEval = kernelTrans(sVs, datMat[i, :], ('rbf', k1))
# 根据支持向量的点计算超平面,返回预测结果
predict = kernelEval.T * np.multiply(labelSV, alphas[svInd]) + b
# 返回数组中各元素的正负号,用1和-1表示,并统计错误个数
if np.sign(predict) != np.sign(labelArr[i]):
errorCount += 1
# 打印错误率
print('训练集错误率:%.2f%%' % ((float(errorCount) / m) * 100))
# showDataSet(dataArr, labelMat)
# 加载测试集
dataArr = testDataArr
labelArr = testLabelArr
errorCount = 0
datMat = np.mat(dataArr)
labelMat = np.mat(labelArr).transpose()
m, n = np.shape(datMat)
for i in range(m):
# 计算各个点的核
kernelEval = kernelTrans(sVs, datMat[i, :], ('rbf', k1))
# 根据支持向量的点计算超平面,返回预测结果
predict = kernelEval.T * np.multiply(labelSV, alphas[svInd]) + b
# 返回数组中各元素的正负号,用1和-1表示,并统计错误个数
if np.sign(predict) != np.sign(labelArr[i]):
errorCount += 1
# 打印错误率
print('测试集错误率:%.2f%%' % ((float(errorCount) / m) * 100))
return (float(errorCount) / m) * 100
if __name__ == '__main__':
sumerrorrate = 0.0
for i in range(10):
sumerrorrate += testRbf()
print("第%d次测试完成" % i)
print("平均错误率:%.2f%%" % (sumerrorrate / 10))
运行结果如下:
具体代码可以参见:
https://github.com/vistor985/-.git