逻辑回归–多元分类问题
有多少类别,就要训练多少二元分类器。每次选择一个类别作为正例,标签为1,其他所有类别都视为负例,标签为0,以此类推至所有的类别。训练好多个二元分类器之后,做预测时,将所有的二元分类器都运行一遍,然后对每一个输入样本,选择最高可能性的输出概率,即为该样本多元分类的类别。
举例来说,如果对3个二元分类器分别做一次逻辑回归,机器的分类结果告诉我们,数据A是孔雀的可能性为0.5,是熊猫的可能性为0.1,是独角兽的可能性为0.4。
那就会判断数据A是孔雀。
一、多元分类的损失函数
多元分类的损失函数的选择与输出编码
,与标签的格式
有关。
多元分类的标签共有以下两种格式。
-
一种是one-hot格式的分类编码,比如,数字0~9分类中的数字8,格式为[0,0,0, 0,0,0,0,1,0]。
-
一种是直接转换为类别数字,如1、2、3、4。
因此损失函数也有以下两种情况。
-
如果通过one-hot分类编码输出标签,则应使用==分类交叉熵(categorical crossentropy)==作为损失函数。
-
如果输出的标签编码为类别数字,则应使用==稀疏分类交叉熵(sparse categorical crossentropy)==作为损失函数。
二、正则化,欠拟合和过拟合
2.1正则化
可以理解为调整模型,约束权重。
机器学习中的正则化是在损失函数里面加惩罚项,增加建模的模糊性,从而把捕捉到的趋势
从局部细微趋势,调整到整体大概趋势。虽然一定程度上地放宽了建模要求,但是能有效防止过拟合的问题,增加模型准确性。它影响的是模型的权重。
2.2 欠拟合和过拟合
3个机器学习模型对数据集的拟合
寻找模型优化和泛化的平衡点
3个分类器的分类边界
2.3 降低过拟合现象的方法。
- 增加数据集的数据个数:数据量太小时,非常容易过拟合,因为小数据集很容易精确拟合。
- 找到模型优化时的平衡点:比如,选择迭代次数,或者选择相对简单的模型。
- 正则化:为可能出现过拟合现象的模型增加正则项,通过降低模型在训练集上的精度来提高其泛化能力,这是非常重要的机器学习思想之一。
2.4 正则化参数
机器学习中的正则化通过引入模型参数λ(lambda)来实现。
加入了正则化参数之后的线性回归均方误差损失函数公式被更新成下面这样:
L ( w , b ) = M S E = 1 N ∑ ( x , y ) ∈ D ( y − h ( x ) ) 2 + λ 2 N ∑ i = 1 n w i 2 L(w,b)=MSE=\frac{1}{N}\sum_{(x,y)\in D}(y-h(x))^2+\frac{\lambda}{2N}\sum_{i=1}^nw_i^2 L(w,b)=MSE=N1(x,y)∈D∑(y−h(x))2+2Nλi=1∑nwi2
加入了正则化参数之后的逻辑回归均方误差损失函数公式被更新成下面这样:
L ( w , b ) = − 1 N ∑ ( x , y ) ∈ D [ y ∗ log ( h ( x ) ) + ( 1 − y ) ∗ log ( 1 − h ( x ) ) ] + λ 2 N ∑ j = 1 n w j 2 L(w,b)=-\frac{1}{N}\sum_{(x,y)\in D}[y^*\log(h(x))+(1-y)*\log(1-h(x))]+\frac{\lambda}{2N}\sum_{j=1}^nw_j^2 L(w,b)=−N1(x,y)∈D∑[y∗log(h(x))+(1−y)∗log(1−h(x))]+2Nλj=1∑nwj2
现在的训练优化算法是一个由两项内容组成的函数:一个是损失项,用于衡量模型与数据的拟合度;另一个是正则化项,用于调解模型的复杂度。
其实,正则化的本质,就是崇尚简单化。同时以最小化损失和复杂度为目标,这称为结构风险最小化。
选择λ值的目标是在简单化和训练集数据拟合之间达到适当的平衡。
如果λ值过大,则模型会非常简单,将面临数据欠拟合的风险。
此时模型无法从训练数据中获得足够的信息来做出有用的预测。而且λ值越大,机器收敛越慢。
如果λ值过小,则模型会比较复杂,将面临数据过拟合的风险。
此时模型由于获得了过多训练数据特点方面的信息而无法泛化到新数据。
将λ设为0可彻底取消正则化。在这种情况下,训练的唯一目的是最小化损失,此时过拟合的风险较高。
正则化参数通常有L1正则化和L2正则化两种选择。
L1正则化,根据权重的绝对值的总和来惩罚权重。在依赖稀疏特征的模型中,L1正则化有助于使不相关或几乎不相关的特征的权重正好为0,从而将这些特征从模型中移除。
L2正则化,根据权重的平方和来惩罚权重。
L2 正则化有助于使离群值(具有较大正值或较小负值)的权重接近于0,但又不会正好为0。
在线性模型中,L2 正则化比较常用,而且在任何情况下都能够起到增强泛化能力的目的。
而最佳λ值则取决于具体数据集,需要手动或自动进行调整。
三、通过逻辑回归解决多元分类问题
3.1数据的分析与准备工作
import numpy as np # 导入Numpy
import pandas as pd # 导入Pandas
from sklearn import datasets # 导入sklearn的数据集
iris = datasets.load_iris() # 导入iris
X_sepal = iris.data[:,[0,1]] # 花萼特征集:两个特征长和宽
X_petal = iris.data[:,[2,3]] # 花瓣特征集:两个特征长和宽
y = iris.target # 标签集
下面进行花萼数据集的分割和标准化,分成训练集和测试集:
from sklearn.model_selection import train_test_split # 导入拆分数据集工具
from sklearn.preprocessing import StandardScaler # 导入标准化工具
X_train_sepal, X_test_sepal, y_train_sepal, y_test_sepal = \train_test_split(X_sepal,y,test_size=0.3,random_state=0) # 拆分数据集
print("花萼训练集样本数: ", len(X_train_sepal))
print("花萼测试集样本数: ", len(X_test_sepal))
scaler = StandardScaler() # 标准化工具
X_train_sepal = scaler.fit_transform(X_train_sepal) # 训练集数据标准化
X_test_sepal = scaler.transform(X_test_sepal) # 测试集数据标准化
# 合并特征集和标签集,留待以后数据展示之用
X_combined_sepal = np.vstack((X_train_sepal,X_test_sepal)) # 合并特征集
Y_combined_sepal = np.hstack((y_train_sepal,y_test_sepal)) # 合并标签集
3.2 通过Sklearn实现逻辑回归的多元分类
from sklearn.linear_model import LogisticRegression # 导入逻辑回归模型
lr = LogisticRegression(penalty='l2', C = 0.1) # 设定L2正则化和C参数
lr.fit(X_train_sepal,y_train_sepal) # 训练机器
score = lr.score(X_test_sepal,y_test_sepal) # 测试集分数评估
print("SK-learn逻辑回归测试准确率 {:.2f}%".format(score*100))
SK-learn逻辑回归测试准确率 68.89%
3.3 正则化参数–c值的选择
用绘图的方式显示出采用不同的C值,对于鸢尾花分类边界的具体影响。
import matplotlib.pyplot as plt # 导入matplotlib
from matplotlib.colors import ListedColormap # 导入Colormap
def plot_decision_regions(X,y,classifier,test_idx=None,resolution=0.02): markers = ('o','x','v')colors = ('red','blue','lightgreen')color_Map = ListedColormap(colors[:len(np.unique(y))]) x1_min = X[:,0].min() - 1x1_max = X[:,0].max() + 1x2_min = X[:,1].min() - 1x2_max = X[:,1].max() + 1xx1, xx2 = np.meshgrid(np.arange(x1_min,x1_max,resolution),np.arange(x2_min,x2_max,resolution)) Z = classifier.predict(np.array([xx1.ravel(),xx2.ravel()]).T)Z = Z.reshape(xx1.shape) plt.contour(xx1,xx2,Z,alpha=0.4,cmap = color_Map)plt.xlim(xx1.min(),xx1.max())plt.ylim(xx2.min(),xx2.max()) X_test, Y_test = X[test_idx,:], y[test_idx]for idx, cl in enumerate(np.unique(y)):plt.scatter(x = X[y == cl, 0], y = X[y == cl, 1],alpha = 0.8, c = color_Map(idx),marker = markers[idx], label = cl)
然后使用不同的C值进行逻辑回归分类,并绘制分类结果:
from sklearn.metrics import accuracy_score # 导入准确率指标
C_param_range = [0.01,0.1,1,10,100,1000]
sepal_acc_table = pd.DataFrame(columns = ['C_parameter','Accuracy'])
sepal_acc_table['C_parameter'] = C_param_range
plt.figure(figsize=(10, 10))
j = 0
for i in C_param_range:lr = LogisticRegression(penalty = 'l2', C = i,random_state = 0)lr.fit(X_train_sepal,y_train_sepal)y_pred_sepal = lr.predict(X_test_sepal)sepal_acc_table.iloc[j,1] = accuracy_score(y_test_sepal,y_pred_sepal)j += 1 plt.subplot(3,2,j)plt.subplots_adjust(hspace = 0.4)plot_decision_regions(X = X_combined_sepal, y = Y_combined_sepal, classifier = lr, test_idx = range(0,150))plt.xlabel('Sepal length')plt.ylabel('Sepal width')plt.title('C = %s'%i)
lr = LogisticRegression(penalty='l2', C = 10) # 设定L2正则化和C参数
lr.fit(X_train_sepal,y_train_sepal) # 训练机器
score = lr.score(X_test_sepal,y_test_sepal) # 测试集分数评估
print("Sklearn逻辑回归测试准确率 {:.2f}%".format(score*100))
Sklearn逻辑回归测试准确率 80.00%