逻辑回归算法实验
一、逻辑回归介绍
- 逻辑回归是一种分类模型
- 逻辑回归通过sigmoid函数将输入值映射到 [0,1] 的区间范围。
- 逻辑回归的目标函数:
因此,当目标函数最小时,w的值,就是我们要求的最终权重值。
二、算法实现
1、鸢尾花的数据集
- 通过sklearn的包导入鸢尾花的数据集:
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
- 用pd.DataFrage函数对数据集的显示进行整理:
iris = load_iris()
data = pd.DataFrame(iris.data, columns=iris.feature_names) # 通过 pd.DataFrame 函数对数据集进行更清晰的展示
data['Kind'] = iris['target'] # 插入列表 (kind表示花的种类)
data = data[data["Kind"] != 2] # 该实验只用到前两类的鸢尾花,故删除第三类。
- 增加增加表格的列数行数和每行的宽度以此让数据集完整表示
pd.set_option('display.max_rows', 1000) # 行数
pd.set_option('display.max_columns', 1000) # 列数
pd.set_option('display.width', 1000) # 宽度
- 数据集展示:
print(data)
2、具体的函数实现
class LogisticRegression:
"""使用python语言来实现逻辑回归算法。"""
def __init__(self, alpha, times):
""""初始化方法。
:parameter
alpha : float
学习率。(用来在梯度下降的时候我们每次更新的步伐)
times : int
迭代次数。
"""
self.alpha = alpha
self.times = times
def sigmoid(self, z):
""""sigmoid函数的实现
:parameter
-----
z: float
自变量,值为z = w^T * x
:returns
-----
p : float,值为[0,1]之间。
返回样本属于类别1的概率值,用来作为结果的预测。
当 s>=0.5(z>=0)时,判定为类别1,否则判定为类别0。
"""
return 1.0/(1.0 + np.exp(-z))
def fit(self, X, y):
"""根据提供的训练数据X,对模型进行训练。
:parameter
X:类数组类型。形状:[样本数量,特征数量]
待训练的样本特征属性。
y:类数组类型,形状:[样本数量]
每个样本的目标值。(标签)
"""
X = np.asarray(X)
y = np.asarray(y)
# 创建权重的向量,初始值为0,长度比特征数多1。(多出来的一个是截距)
self.w_ = np.zeros(1 + X.shape[1])
# 创建损失列表,用来保存每次迭代后的损失值。
self.loss_ = []
for i in range(self.times):
z = np.dot(X, self.w_[1:]) + self.w_[0]
# 计算概率值(结果判定为1的概率)
p = self.sigmoid(z)
# 根据逻辑回归的代价函数(目标函数),计算损失值。
# 逻辑回归的代价函数(目标函数):
cost = -np.sum(y * np.log(p) + (1-y) * np.log(1 - p))
self.loss_.append(cost)
# 调整权重值,根据公式:调整为:权重(j列) = 权重(j列)+ 学习率*sum((y-s(z))* x(j))
self.w_[0] += self.alpha * np.sum(y-p)
self.w_[1:] += self.alpha * np.dot(X.T, y-p)
def predict_proba(self, X):
"""根据参数传递的样本,对样本数据进行预测。
:parameter
-----
X: 类数组类型。形状为[样本数量,特征数量]
待预测的样本特征(属性)
:returns
---
result:数组类型
预测的结果(概率值)
"""
X = np.asarray(X)
z = np.dot(X, self.w_[1:]) + self.w_[0]
p = self.sigmoid(z)
# 将预测结果变成二维数组(结构)。便于后续拼接。
p = p.reshape(-1, 1)
# 将两个数组进行拼接。方向为横向拼接
return np.concatenate([1-p, p], axis=1)
def predict(self, X):
"""根据参数传递的样本,对样本数据进行预测。
:parameter
-----
X : 类数组类型。[样本数量,特征数量]
待测试的样本特征(属性)
:returns
-----
result :数组类型。
预测的结果(分类值)
"""
return np.argmax(self.predict_proba(X), axis=1)
- 对训练集和测试集进行划分:
t1 = data[data["Kind"]==0]
t2 = data[data["Kind"]==1]
t1 = t1.sample(len(t1), random_state=0)
t2 = t2.sample(len(t2), random_state=0)
train_X = pd.concat([t1.iloc[:40, :-1], t2.iloc[:40, :-1]], axis=0)
train_y = pd.concat([t1.iloc[:40, -1], t2.iloc[:40, -1]], axis=0)
test_X = pd.concat([t1.iloc[40:, :-1], t2.iloc[40:, :-1]], axis=0)
test_y = pd.concat([t1.iloc[40:, -1], t2.iloc[40:, -1]], axis=0)
- 开始预测:
# 鸢尾花的特征列都在同一个数量级,我们这里不用进行标准化处理
lr = LogisticRegression(alpha=0.01, times=20)
lr.fit(train_X, train_y)
probability = lr.predict_proba(test_X) # 预测的概率值
result = lr.predict(test_X) # 预测的结果
accuracy = np.sum(result==test_y) / len(test_y) # 预测结果的准确性
- 打印预测结果:
print(probability)
print(result)
print(accuracy)
3、可视化
- 调用画图库:
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rcParams["font.family"] = "SimHei" # 字体为黑体
mpl.rcParams["axes.unicode_minus"] = False # 解决保存图像是负号'-'显示为方块的问问题
- 绘制图:
# 绘制预测值
plt.plot(result, "ro", ms=15, label="预测值")
#绘制真实值
plt.plot(test_y.values, "go", label="真实值")
plt.title("逻辑回归")
plt.xlabel("样本序号")
plt.ylabel("类别")
plt.legend()
plt.show()
- 绘制目标函数的损失值图像:
# 绘制目标函数的损失值图像
plt.plot(range(1, lr.times+1), lr.loss_, "go-")
plt.show()