作者:欧新宇(Xinyu OU)
本文档所展示的测试结果,均运行于:Intel Core i7-7700K CPU 4.2GHz
构建一个模型,根据鸢尾花的花萼长度、花萼宽度、花瓣长度和花瓣宽度将一朵鸢尾花分为三种不同的品种。
具体任务包括:
鸢尾花数据集总共包含150个数据,每个种类的鸢尾花都是50个样本,每个样本都包含4个特征:花萼长度、花萼宽度、花瓣长度和花瓣宽度。目标值为3种不同的鸢尾花:{0:山鸢尾, 1:变色鸢尾, 2: 维吉尼亚鸢尾}
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn import svm # 导入SVM支持向量机包
from sklearn import neural_network # 导入MLP神经网络包
(1) 下载鸢尾花数据集(百度AI Studio - 数据集 - 鸢尾花数据集(完整版)“宇宙骑士, 2020-05-02,iris.csv”)
(2) 观察鸢尾花数据集的构成和特点,并将数据集按照训练集和测试集的模式进行分割。分割比例要求2:8。
def prepare_datasets(show_examples = False):
# 使用pandas载入数据集
data = pd.read_csv('../Datasets/iris.csv')
# 将类别名称转换成编码
data.loc[data.Species=='Iris-setosa', 'Species']='0'
data.loc[data.Species=='Iris-versicolour', 'Species']='1'
data.loc[data.Species=='Iris-virginica', 'Species']='2'
if show_examples == True:
# 观察数据集,取前5个样本
print(data.head())
# 将数据中的特征和标签进行分离,其中第0位位索引号,第1-8位位特征,第9位为标签
X = data.iloc[:, 0:4]
y = data.iloc[:, 4]
# 以 20%:80%的比例对训练集和测试集进行拆分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.8, random_state=1)
return X_train, X_test, y_train, y_test
# X_train, X_test, y_train, y_test = prepare_datasets(show_examples=True)
C越大,相当于惩罚松弛变量,希望松弛变量接近0,即对误分类的惩罚增大,趋向于对训练集全分对的情况,这样对训练集测试时准确率很高,但泛化能力弱。 C值小,对误分类的惩罚减小,允许容错,将他们当成噪声点,泛化能力较强。
kernel='linear'时,为线性核
decision_function_shape='ovr'时,为one v rest,即一个类别与其他类别进行划分,
decision_function_shape='ovo'时,为one v one,即将类别两两之间进行划分,用二分类的方法模拟多分类的结果。
def SVM():
model_name = 'SVM'
#model = svm.SVC(C=0.8,kernel='rbf', gamma=50,decision_function_shape='ovr')
model = svm.SVC(C=0.5, #误差项惩罚系数,默认值是1
kernel='rbf', #kernel= {线性核: 'linear', 高斯核: kenrel="rbf"}
decision_function_shape='ovr', #决策函数
gamma='auto')
return model, model_name
# model
其他在参数在真实应用中再进行讲解和设置
def MLP():
model_name = 'MLP'
model = neural_network.MLPClassifier(
solver='lbfgs', # 优化器solver={'lbfgs', 'sgd', 'adam'}
hidden_layer_sizes=[128,64,128], # 隐层单元
activation='relu', # 激活函数activation={'identity', 'logistic', 'tanh', 'relu'}
alpha=1e-5) # 正则化参数
return model, model_name
def train(model, x_train,y_train):
model.fit(X_train, #训练集特征向量
y_train.ravel()) #训练集目标值
# train(model, X_train, y_train)
def print_results(model, model_name, X_train, y_train, X_test, y_test):
print('{}模型:'.format(model_name))
#分别打印训练集和测试集的准确率 score(X_train,y_train):表示输出X_train,y_train在模型上的准确率
print('训练集评分: {:.3f}'.format(model.score(X_train, y_train)))
print('测试集评分: {:.3f}'.format(model.score(X_test, y_test)))
#计算决策函数的值,表示x到各分割平面的距离(该函数只支持SVM)
# print('decision_function:\n', clf.decision_function(X_train))
# print_results(model,X_train,y_train,X_test,y_test)
def predict(model, test_id):
print('待预测样本编号为:{},原始标签为:{},预测标签为:{}。'.format(
test_id, # 基于测试集的id,值得注意的是测试集的划分是随机的,因此与原编号不一致
np.array(y_test)[test_id], # 将df数据转换成numpy数组,并通过新的索引获取数据
model.predict([np.array(X_test)[test_id]])[0])) # 将测试样本也转换成2Dnumpy数组,实现新索引关联。注意需要将样本转换为2D数组。
if __name__ == '__main__':
# Step0. 全局超参数配置
test_id = 113 #测试集样本编号
# Step1. 准备数据集
# X_train, X_test, y_train, y_test = prepare_datasets(show_examples = True)
X_train, X_test, y_train, y_test = prepare_datasets()
# Step2. 定义模型:SVM模型定义
model, model_name = SVM()
# model, model_name = MLP()
# Step3. 启动训练过程
train(model, X_train, y_train)
# Step4. 模型评估
print_results(model, model_name, X_train, y_train, X_test, y_test)
# Step5: 样本预测
predict(model, test_id)
# MLP模型:
# 训练集评分: 1.000
# 测试集评分: 0.942
# 待预测样本编号为:113,原始标签为:0,预测标签为:0。
# SVM模型:
# 训练集评分: 1.000
# 测试集评分: 0.925
# 待预测样本编号为:113,原始标签为:0,预测标签为:0。