机器学习--svm算法一些参数调节demo

1.这里生成一些样本点,然后使用svm里面的径向基函数作为核方法,分别使用ovo和ovr方法进行实验:

import numpy as np
from sklearn import svm
from scipy import stats
from sklearn.metrics import accuracy_score
import matplotlib as mpl
import matplotlib.pyplot as plt

def extend(a, b, r):
	x = a - b
	m = (a + b) / 2
	return m - r*x/2, m + r*x/2

if __name__ == '__main__':
	np.random.seed(0)
	N = 20
	x = np.empty((4*N, 2))
	# print(x)
	means = [(-1, 1), (1, 1), (1, -1), (-1, -1)]
	sigmas = [np.eye(2), 2*np.eye(2), np.diag((1, 2)), np.array(((2, 1), (1, 2)))]
	for i in range(4):
		mn = stats.multivariate_normal(means[i], sigmas[i]*0.3)
		x[i*N:(i+1)*N, :] = mn.rvs(N)
	a = np.array((0, 1, 2, 3)).reshape((-1, 1))
	y = np.tile(a, N).flatten()
	clf = svm.SVC(C=1, kernel='rbf', gamma=1, decision_function_shape='ovr')
	# clf = svm.SVC(C=1, kernel='rbf', gamma=1, decision_function_shape='ovo')
	clf.fit(x, y)
	y_hat = clf.predict(x)
	acc = accuracy_score(y, y_hat)
	np.set_printoptions(suppress=True)
	print('True prediction numbers:%d, predictions:%.3f%%' %(round(acc*4*N), 100*acc))
	print('decision_function:\n', clf.decision_function(x))
	print('y_hat:\n', y_hat)
	# 开始画图
	x1_min, x2_min = np.min(x, axis=0)
	x1_max, x2_max = np.max(x, axis=0)
	x1_min, x1_max = extend(x1_min, x1_max, 1.05)
	x2_min, x2_max = extend(x2_min, x2_max, 1.05)
	# 生成网格采样点
	x1, x2 = np.mgrid[x1_min:x1_max:500j, x2_min:x2_max:500j]
	x_test = np.stack((x1.flat, x2.flat), axis=1)
	y_test = clf.predict(x_test)
	y_test = y_test.reshape(x1.shape)

	cm_light = mpl.colors.ListedColormap(['#A0FFA0', '#FFA0A0', '#A0A0FF'])
	cm_dark = mpl.colors.ListedColormap(['g', 'b', 'r'])
	plt.figure(facecolor='w')
	plt.pcolormesh(x1, x2, y_test, cmap=cm_light)
	plt.scatter(x[:, 0], x[:, 1], s=40, c=y, cmap=cm_dark, alpha=0.7)
	plt.xlim((x1_min, x1_max))
	plt.ylim((x2_min, x2_max))
	plt.grid(True)
	plt.tight_layout(pad=2.5)
	plt.title('SVM Metholds--one/one or one/other', fontsize=18)
	plt.show()

ovo:


ovr:


由于数据的问题,这里基本看不出什么差别,具体哪种方法孰优孰劣具体看不同的数据集。

code2:

import numpy as np
from sklearn import svm
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.colors

def extend(a, b):
	return (1.01*a - 0.01*b), (1.01*b - 0.01*a)

if __name__ == '__main__':
	t = np.linspace(-5, 5, 6)
	t1, t2 = np.meshgrid(t, t)
	x1 = np.stack((t1.ravel(), t2.ravel()), axis=1)
	N = len(x1)
	x2 = x1 + (1, 1)
	x = np.concatenate((x1, x2))
	y = np.array([1]*N + [-1]*N)

	clf = svm.SVC(C=0.1, kernel='rbf', gamma=5)
	clf.fit(x, y)
	y_hat = clf.predict(x)
	print('Accuracy:%.3f%%' %(np.mean(y_hat == y) * 100))

	# 开始画图
	cm_light = mpl.colors.ListedColormap(['#A0FFA0', '#FFA0A0'])
	cm_dark = mpl.colors.ListedColormap(['g', 'b'])
	x1_min, x1_max = extend(x[:, 0].min(), x[:, 0].max())
	x2_min, x2_max = extend(x[:, 1].min(), x[:, 1].max())
	# 生成网格采样点
	x1, x2 = np.mgrid[x1_min:x1_max:500j, x2_min:x2_max:500j]
	x_test = np.stack((x1.flat, x2.flat), axis=1)
	y_test = clf.predict(x_test)
	y_test = y_test.reshape(x1.shape)
	
	plt.figure(facecolor='w')
	plt.pcolormesh(x1, x2, y_test, cmap=cm_light)
	plt.scatter(x[:, 0], x[:, 1], s=40, c=y, cmap=cm_dark, alpha=0.7)
	plt.xlim((x1_min, x1_max))
	plt.ylim((x2_min, x2_max))
	plt.grid(True)
	plt.tight_layout(pad=2.5)
	plt.title('SVM Metholds RBF Overfiting', fontsize=18)
	plt.show()

code3:

import numpy as np
from sklearn import svm
from sklearn.model_selection import GridSearchCV
import matplotlib.pyplot as plt

if __name__ == '__main__':
	N = 50
	np.random.seed(0)
	x = np.sort(np.random.uniform(0, 6, N), axis=0)
	y = 2*np.sin(x) + 0.1*np.random.randn(N)
	x = x.reshape(-1, 1)
	print('x:\n', x)
	print('y:\n', y)

	print('--------SVR RBF---------')
	svr_rbf_model = svm.SVR(kernel='rbf', gamma=0.2, C=100)
	svr_rbf_model.fit(x, y)
	
	print('--------SVR Linear---------')
	svr_linear_model = svm.SVR(kernel='linear', C=100)
	svr_linear_model.fit(x, y)
	
	print('--------SVR Polynomial---------')
	svr_poly_model = svm.SVR(kernel='poly', degree=3, C=100)
	svr_poly_model.fit(x, y)
	

	x_test = np.linspace(x.min(), 1.5*x.max(), 100).reshape(-1, 1)
	y_hat_rbf = svr_rbf_model.predict(x_test)
	y_hat_linear = svr_linear_model.predict(x_test)
	y_hat_poly = svr_poly_model.predict(x_test)
	
	plt.figure(figsize=(10, 10), facecolor='w')
	# plt.scatter(x[sp], y[sp], s=120, c='r', marker='*', label='Support Vectors', zorder=3)
	plt.plot(x_test, y_hat_rbf, 'r-', lw=2, label='RBF Kernel')
	plt.plot(x_test, y_hat_linear, 'g-', lw=2, label='linear Kernel')
	plt.plot(x_test, y_hat_poly, 'b-', lw=2, label='poly Kernel')
	plt.plot(x, y, 'go', markersize=5)
	plt.legend(loc='upper right')
	plt.title('1.1 SVR', fontsize=16)
	plt.xlabel('x')
	plt.ylabel('y')
	plt.grid(True)
	plt.show()



接着使用一个数据集:bipartition.txt(其实就是生成的一堆3维数据:

import numpy as np
from sklearn import svm
import matplotlib as mpl
import matplotlib.colors
import matplotlib.pyplot as plt

def show_accuracy(a, b):
	acc = a.ravel() == b.ravel()
	print('the acc:%.3f%%' % (100*float(acc.sum()) / a.size))

if __name__ == '__main__':
	data = np.loadtxt('bipartition.txt', dtype=np.float, delimiter='\t')
	x, y = np.split(data, (2,), axis=1)
	y[y == 0] = -1
	y = y.ravel()
	print(x)
	print(y)

	# 设置分类器,进行调参
	clf_param = (('linear', 0.1), ('linear', 0.5), ('linear', 1), ('linear', 2),
		('rbf', 1, 0.1), ('rbf', 1, 1), ('rbf', 1, 10), ('rbf', 1, 100),
		('rbf', 5, 0.1), ('rbf', 5, 1), ('rbf', 5, 10), ('rbf', 5, 100))

	# 开始画图
	x1_min, x1_max = x[:, 0].min(), x[:, 0].max()
	x2_min, x2_max = x[:, 1].min(), x[:, 1].max()
	# 生成网格采样点
	x1, x2 = np.mgrid[x1_min:x1_max:200j, x2_min:x2_max:200j]
	# 测试点
	grid_test = np.stack((x1.flat, x2.flat), axis=1)
	cm_light = mpl.colors.ListedColormap(['#A0FFA0', '#FFA0A0'])
	cm_dark = mpl.colors.ListedColormap(['g', 'b'])

	plt.figure(figsize=(14, 14), facecolor='w')
	for i, param in enumerate(clf_param):
		# print(param)
		clf = svm.SVC(C=param[1], kernel=param[0])
		if param[0] == 'rbf':
			clf.gamma = param[2]
			title = 'Ga K, C=%.1f, gamma=%.1f' %(param[1], param[2])
		else:
			title = 'linear kernel, C=%.1f' %param[1]

		clf.fit(x, y)
		y_hat = clf.predict(x)
		show_accuracy(y_hat, y)

		# 画图
		print(title)
		print('the numbers of support vectors:\n', clf.n_support_)
		print('the params of support vectors:\n', clf.dual_coef_)
		print('the support vectors:\n', clf.support_)
		plt.subplot(3, 4, i+1)
		grid_hat = clf.predict(grid_test)
		grid_hat = grid_hat.reshape(x1.shape)
		plt.pcolormesh(x1, x2, grid_hat, cmap=cm_light, alpha=0.8)
		plt.scatter(x[:, 0], x[:, 1], c=y, edgecolor='k', s=40, cmap=cm_dark)
		plt.scatter(x[clf.support_, 0], x[clf.support_, 1], edgecolor='k', facecolor='none', s=100, marker='o')
		z = clf.decision_function(grid_test)
		z = z.reshape(x1.shape)
		plt.contour(x1, x2, z, colors=list('kmrmk'), linestyles=['--', '-', '--', '-', '--'], 
			lw=[1, 0.5, 1.5, 0.5, 1], levels=[-1, -0.5, 0, 0.5, 1])
		plt.xlim(x1_min, x1_max)
		plt.ylim(x2_min, x2_max)
		plt.title(title, fontsize=13)
	plt.suptitle('different params in svm classification', fontsize=20)
	plt.tight_layout(2.0)
	plt.subplots_adjust(top=0.90)
	plt.show()

调参经验总结:对于线性核函数,C参数越小,其算法的泛化能力相对要较强,然后过渡带要宽一些,C越大,要求算法分类误差要尽量小,因此准确率要较高,但也可能在训练集上出现overfitting。对于高斯核函数,C的调参效果和线性核一样,但是gamma参数越小其算法分类精确度要偏低,但是泛化能力较强。

猜你喜欢

转载自blog.csdn.net/oliverkingli/article/details/80655553