说明:数据同Logistic回归
# python 2.7 python 2.7 python 2.7 #import必要的模块 import pandas as pd import numpy as np from sklearn.model_selection import GridSearchCV from sklearn import metrics from sklearn.metrics import accuracy_score from matplotlib import pyplot import seaborn as sns %matplotlib inline
#读取数据 dpath = './logistic/' train = pd.read_csv(dpath + "Otto_train_test.csv") train.head()
train.info()
......
#各属性的统计特性 train.describe()
# Target 分布,查看各类样本分布是否均衡 # 当各类样本数量不均衡时,交叉验证对分类任务要采用StratifiedKFold,即在每折采样时根据各类样本按比例采样, # 交叉验证的代码中缺省的就是StratifiedKFold sns.countplot(train.target) pyplot.xlabel('target') pyplot.ylabel('Number of occurrences')
# 将类别字符串变成数字 y_train = train['target'] #形式为Class_x y_train = y_train.map(lambda s: s[6:]) y_train = y_train.map(lambda s: int(s) - 1) train = train.drop(["id" , "target"] , axis = 1) X_train = np.array(train)
# 数据标准化 from sklearn.preprocessing import StandardScaler # 初始化特征的标准化器 ss_X = StandardScaler() # 分别对训练和测试数据的特征进行标准化处理 X_train = ss_X.fit_transform(X_train) # 因采用的是交叉验证,所以没有划分出训练数据和测试数据 #X_test = ss_X.transform(X_test)
# 训练样本大时,交叉验证太慢,用train_test_split估计模型性能 from sklearn.model_selection import train_test_split X_train_part , X_val , y_train_part , y_val = train_test_split(X_train , y_train , random_state=33 , test_size=0.2)
#线性SVM from sklearn.svm import LinearSVC SVC1 = LinearSVC().fit(X_train_part , y_train_part)
#在校验集上测试,估计模型性能 y_predict = SVC1.predict(X_val) print("sklearn中线性SVM的默认参数: \n%s:\n模型分类结果\n%s\n" % (SVC1 , metrics.classification_report(y_val , y_predict))) print("混淆矩阵 :\n %s" % (metrics.confusion_matrix(y_val , y_predict)))
out:
混淆矩阵对角线性上是分类分对的样本,非对角线上的是分错的样本,比如矩阵的第一行,第一个4表示:该4个样本点应该是第一类,分类判断也是第一类(分类正确),矩阵第一行最后面的5则表示:这5个样本应该是第一类的,但却被分成了第9类; 模型分类结果中: precision(查准率)表示被模型的预测结果中,每类预测正确的样本数/每类预测的总数,如混淆矩阵中的第一列,第一列的总数为4+1+6=11,表示模型将141个样本的11个分成了第一类,其中第一行第一列的4,表示这4个样本是第一类,且被分到了第一类(分类正确),第9行第一列的6,表示有6个第9类的样本数被模型错分到了第一类,第7行第一列的1同理,因此,第一类的查准率为4/4+1+6 = 0.36; recall(查全率)表示用于模型预测的数据中,每类预测对的数量/每类实际的总数,如混淆矩阵中的第一列表示用于模型预测中的数据中,第一类样本的总数为4+4+5=13,分对的为4,为错的为4+5,因此查全率为4/4+4+5=0.31; f1-score是precision和recall的加权平均,计算公式为:f1 = 2(precisionrecall) / (precision+recall);
线性SVM LinearSVC中,需要调整的正则超参数包括:C(正则系数,一般在log域(取log后的值)均匀设置候选参数),penalty(正则函数L2/L1); 参数确定的方式采用交叉验证,网格搜索步骤同Logistic回归的正则参数处理类似;这里用校验集(X_val , y_val)来估计模型性能;
def fit_grid_point_Linear(C , X_train , y_train , X_val , y_val): #在训练集利用SVC训练 SVC2 = LinearSVC(C = C) SVC2 = SVC2.fit(X_train , y_train) #在校验集上返回accuracy accuracy = SVC2.score(X_val , y_val) print("accuracy:{}".format(accuracy)) return accuracy
#需要调优的参数 C_s = np.logspace(-4 , 3 , 7)#logspace(a , b , N)把10的a次方到10的b次方分成N个等比数列 penalty_s = ['l1' , 'l2'] accuracy_s = [] for j , penalty in enumerate(penalty_s): tmpArr = [] for i , oneC in enumerate(C_s): tmp = fit_grid_point_Linear(oneC , X_train , y_train , X_val , y_val) tmpArr.append(tmp) accuracy_s.append(tmpArr) x_axis = np.log10(C_s) for j , penalty in enumerate(penalty_s): pyplot.plot(x_axis , np.array(accuracy_s[j]) , '2-') pyplot.legend() pyplot.xlabel('log(C)') pyplot.ylabel('accuracy') pyplot.savefig('SVM_Otto.png') pyplot.show()
out:
RBF核是SVM最常用的核函数(没有之一)。RBF核SVM的需要调整正则超参数包括C(正则系数,一般在log域(取log后的值)均匀设置候选参数)和核函数的宽度gamma; 参数确定的方式采用交叉验证,网格搜索步骤同Logistic回归的正则参数处理类似;这里用校验集(X_val , y_val)来估计模型性能;
from sklearn.svm import SVC
def fit_grid_point_RBF(C , gamma , X_train , y_train , X_val , y_val): #在训练集利用SVC训练 SVC3 = SVC(C = C , kernel='rbf' , gamma = gamma) SVC3 = SVC3.fit(X_train , y_train) #在校验集上返回accuracy accuracy = SVC3.score(X_val , y_val) print("accuracy:{}".format(accuracy)) return accuracy
#需要调优的参数 C_s = np.logspace(-2 , 2 ,5)#logspace(a , b , N)把10的a次方到10的b次方区间等分成N份 gamma_s = np.logspace(-2 , 2 , 3) accuracy_s = [] for i , oneC in enumerate(C_s): for j , gamma in enumerate(gamma_s): tmp = fit_grid_point_RBF(oneC , gamma , X_train , y_train , X_val , y_val) accuracy_s.append(tmp)
out:
实际运行中,可以将从已运行的结果查看参数是否合适,不合适时,可以停止模型,重新设置参数; gamma越大,对应RBF核的sigma越小,决策边界更复杂,可能发生了过拟合,所以要调小gamma值;
# 绘制结果 number_C = len(C_s) number_gamma = len(gamma_s) #np中才有array函数,作用是将python中的list转换成array,reshape(a , b)函数则是将array分成一个a行b行的多维数组 accuracy_s1 = np.array(accuracy_s).reshape(number_C , number_gamma) x_axis = np.log10(C_s) #accuracy_s1[: , j]是取accuracy_s1数组中的第j列 for j , gamma in enumerate(gamma_s): pyplot.plot(x_axis , np.array(accuracy_s1[: , j]) , label = 'gamma' + str(gamma)) pyplot.legend() pyplot.xlabel('log(C)') pyplot.ylabel('accuracy') pyplot.savefig('RBF_SVM_Otto.png') pyplot.show()