iris_LogisticRegression_optimization
(1)背景
- 常规任务是利用给定的类别、已知的训练数据来学习分类规则和分类器,然后对未知数据进行分类(或预测)。逻辑回归常用来解决二分类的问题。与线性回归有很多相同之处,去除Sigmoid映射函数的话,逻辑回归算法就是一个线性回归。
(2)基本假设
- 面对一个回归或者分类问题,建立代价函数,然后通过优化方法(通过train_data训练我们的model)迭代求解出最优的模型参数,然后测试验证我们这个求解的模型的好坏
- 优化的部分是不用手动指定迭代次数,原理是当损失函数变化不大时停止迭代,而要实现这个功能我们需要一个期望的差值(exp_gap)对损失函数进行判定,是否可以停止迭代。
二,目标函数
- 是我们最终要优化的函数
三,训练LogisticRegression_model
- 这里简单介绍一下交叉熵损失函数
- 对于在二分类损失函数中应用,交叉熵损失函数为以下形式。
- 在python中的实现为:
第一种实现方法
cost = - np.sum(y * np.log(p) + (1 - y) * np.log(1 - p)) # 损失函数
第二种实现方法
cost = - np.dot(y, np.log(p)) - np.dot(1-y, np.log(1-p))
- 交叉熵能够衡量同一个随机变量中的两个不同概率分布的差异程度,在机器学习中就表示为真实概率分布与预测概率分布之间的差异。
- 交叉熵的值越小,模型预测效果就越好。
- 交叉熵经常搭配softmax使用,将输出的结果进行处理,使其多个分类的预测值和为1,再通过交叉熵来计算损失。
- 参数更新:
self.w_[1:] += self.learning_rate*np.dot(X.T, y - p)
- python实现:
def train(self, X, y):
X = np.asarray(X)
y = np.asarray(y)
self.w_ = np.zeros(1 + X.shape[1])
self.loss_ = []
flag = True
self.times = 0 #迭代次数初始化为0
while flag:
z = np.dot(X, self.w_[1:]) + self.w_[0]
p = self.Sigmoid(z)
cost = - np.sum(y * np.log(p) + (1 - y) * np.log(1 - p))/len(y) # 损失函数
# cost = - np.dot(y, np.log(p)) - np.dot(1-y, np.log(1-p))
self.loss_.append(cost)
# 通过不断调整权重值,选取最优的参数
self.w_[0] += self.learning_rate*np.sum(y - p)
self.w_[1:] += self.learning_rate*np.dot(X.T, y - p)
self.times += 1 #记录迭代的次数
if self.times != 1 and self.loss_[-2] > self.loss_[-1]:
gap = self.loss_[-2] - self.loss_[-1]
if gap <= self.exp_gap:
break
# self.exp_gap:就是我们期望的差值
四,预测Predict
- 这里使用的
z = np.dot(X, self.w_[1:]) + self.w_[0]
,z的值域为负无穷到正无穷,并不能达到我们想要进行二分类的目的,所以我们引入了sigmoid函数 - 简单介绍一下sigmoid函数:
1.逻辑函数(logistic function)也成为对数几率函数,其函数为:2.典型的Sigmoid函数,他把可能在较大范围内变化的输入值“挤压到”(0,1),输出范围内,因此又时也成为“挤压函数”(squashing function)
3.在分类问题中,我们经常需要找到一个单调可微函数将分类任务的真实标记y(分类结果所得数值一般是0-1之间的数,如0.99,0.35等,当我们需要的结果是0或者1)与线性回归模型的预测值联系起来。
4.考虑二分类任务,其输入标记y∈{0, 1},但实际情况产生值处于0和1之间,如线性回归模型产生的预测值为z = wx +b 实际值。为了实际值转换为0 或者 1。 我们需要一个函数以0.5来区分,最理想的是单位阶跃函数(unti-step function)
y= {0, x<0 ; 1,x > 0}
5.函数图像为:
- 此处Python预测运用了sigmoid函数,进行二分类
def Pre_pro(self, X):
X = np.asarray(X)
z = np.dot(X, self.w_[1:]) + self.w_[0]
p = self.Sigmoid(z)
p = p.reshape(-1, 1)
# print(np.concatenate([1-p, p], axis=1))
return np.concatenate([1-p, p], axis=1)
def Pre(self, X):
# print(self.Pre_pro(X))
return np.argmax(self.Pre_pro(X), axis=1)
五,实验
(1)数据集的使用:
- 这里我选择的是一个简单的数据集–鸢尾花iris。
- 该数据集有5个变量,其中4个特征变量,1个目标分类变量。共有150个样本,目标变量为 花的类别 其都属于鸢尾属下的三个亚属,分别是山鸢尾 (Iris-setosa),变色鸢尾(Iris-versicolor)和维吉尼亚鸢尾(Iris-virginica)。包含的三种鸢尾花的四个特征,分别是花萼长度(cm)、花萼宽度(cm)、花瓣长度(cm)、花瓣宽度(cm),这些形态特征在过去被用来识别物种。
- 数据只选取了其中目标变量为0,1的鸢尾花,现在数据集只有100个样本。
- 代码:
from sklearn.datasets import load_iris
import numpy as np
iris = load_iris()
data = np.concatenate([iris['data'], iris['target'].reshape(-1, 1)], axis=1)
t1 = data[data[:, -1] == 0]
t2 = data[data[:, -1] == 1]
(2)训练集:
# 选取了t1的前35个样本,t2的前35个样本
train_X = np.concatenate([t1[:35, :-1], t2[:35, :-1]], axis=0)
train_y = np.concatenate([t1[:35, -1], t2[:35, -1]], axis=0)
# 对训练集进行打乱
np.random.seed(0)
np.random.shuffle(train_X)
np.random.seed(0)
np.random.shuffle(train_y)
(3)测试集:
# 测试集,选取t1,t2的后35条数据
test_X = np.concatenate([t1[35:, :-1], t2[35:, :-1]], axis=0)
test_y = np.concatenate([t1[35:, -1], t2[35:, -1]], axis=0)
# 对测试集进行打乱
np.random.seed(0)
np.random.shuffle(test_X)
np.random.seed(0)
np.random.shuffle(test_y)
(4)运行结果
- 真实值与预测值:
- Loss值:
六,实验总结
- 这里说说逻辑回归的优缺点:
- 优点:
- 实现简单,广泛的应用于工业问题上;
- 分类时计算量非常小,速度很快,存储资源低;
- 便利的观测样本概率分数;
- 对逻辑回归而言,多重共线性并不是问题,它可以结合L2正则化来解决该问题;
- 计算代价不高,易于理解和实现。
- 缺点:
- 当特征空间很大时,逻辑回归的性能不是很好;
- 容易欠拟合,一般准确度不太高;
- 不能很好地处理大量多类特征或变量;
- 只能处理两分类问题(在此基础上衍生出来的softmax可以用于多分类),且必须线性可分;
- 对于非线性特征,需要进行转换.