SVM支持向量机实现兵王问题

最近在看浙大胡浩基老师的机器学习研究生课程,关于SVM解决国际象棋兵王问题觉得很有意思,其实就是一个二分类问题。

一、问题描述与分析

  • 国际象棋规则:8*8棋盘,黑、白兵各有8个。
  • 兵:第一次向前可以走一格或两格,以后只能向前走一格,不能后退;吃对方子的时候可以斜前方走,并落在对方位置。
  • 王:黑白各一个,王被将死即告负,走法是横着、斜着都可以,但是每次只能走一格。
    兵王问题:国际象棋的残局中,黑方只剩下一个王,白方剩一个兵和一个王。结局只有两种:白方将死黑方获胜,或者和棋。
    SVM支持向量机实现兵王问题_第1张图片

二、数据集

UCI MACHINE LEARNING数据集下载https://archive.ics.uci.edu/ml/index.php
krkopt.data 数据集每一行就是一个训练样本
SVM支持向量机实现兵王问题_第2张图片
总样本数:28056
正样本:2796(yi=+1 ,和棋)
负样本:25260(yi=–1 ,白方胜)

三、程序设计

第一步:数据预处理

随机取5000个样本进行训练,其余测试。
训练样本归一化:训练样本上,求出每个维度的均值和方差。在训练和测试样本上,同时进行归一化
SVM支持向量机实现兵王问题_第3张图片

第二步:设置SVM各种参数

SVM支持向量机实现兵王问题_第4张图片
SVM支持向量机实现兵王问题_第5张图片
SVM支持向量机实现兵王问题_第6张图片
SVM支持向量机实现兵王问题_第7张图片
SVM支持向量机实现兵王问题_第8张图片

四、代码编写

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split,cross_val_score,GridSearchCV
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler

#pandas处理数据集
#sklearn.model_selection实现数据集分割,自动调参
#sklearn.svm线性支持向量分类

# 读取数据
data = pd.read_csv('/testSVMChess/krkopt.data', header=None)
data.dropna(inplace=True)  # 不创建新的对象,直接对原始对象进行修改


def svm_c(x_train, x_test, y_train, y_test):
    # rbf核函数,设置数据权重
    svc = SVC(kernel='rbf', class_weight='balanced',)
    c_range = np.logspace(-5, 15, 11, base=2)
    gamma_range = np.logspace(-9, 3, 13, base=2)
    # 网格搜索交叉验证的参数范围,cv=3,3折交叉
    param_grid = [{'kernel': ['rbf'], 'C': c_range, 'gamma': gamma_range}]
    grid = GridSearchCV(svc, param_grid, cv=3, n_jobs=-1)
    # 训练模型
    clf = grid.fit(x_train, y_train)
    # 计算测试集精度
    score = grid.score(x_test, y_test)
    print('精度为%s' % score)
    

# 样本数值化 a,b,c...h 转化为 1,2,3...8
for i in [0, 2, 4]:
    data.loc[data[i] == 'a', i] = 1
    data.loc[data[i] == 'b', i] = 2
    data.loc[data[i] == 'c', i] = 3
    data.loc[data[i] == 'd', i] = 4
    data.loc[data[i] == 'e', i] = 5
    data.loc[data[i] == 'f', i] = 6
    data.loc[data[i] == 'g', i] = 7
    data.loc[data[i] == 'h', i] = 8
    
# 将标签数值化 -1表示将死,1表示和棋
data.loc[data[6] != 'draw', 6] = -1
data.loc[data[6] == 'draw', 6] = 1

# 归一化处理 Z-score标准化方法 (经过处理的数据符合标准正态分布,即均值为0,标准差为1)
for i in range(6):
    data[i] = (data[i]-data[i].mean())/data[i].std()

# 拆分训练集和测试集    train_teat_split() https://www.cnblogs.com/bonelee/p/8036024.html 省略random_state=0
X_train, X_test, y_train, y_test = train_test_split(data.iloc[:, :6], data[6].astype(int), test_size=0.82178500142572)
svm_c(X_train, X_test, y_train, y_test)

平均正确率99.53%

你可能感兴趣的:(机器学习)