import numpy as np
import pandas as pd
data = pd.read_csv("iris.csv")
#去掉不需要的列
data.drop("id",axis=1,inplace=True)
data.drop_duplicates(inplace=True)
#实现映射操作
data['Species'] = data['Species'].map({'Iris-versicolor':0,'Iris-setosa':1,'Iris-virginica':2})
#对数据进行筛选,只选取类型为0,1的数据,进行逻辑回归二分类
data = data[data['Species'] != 2]
data
class LogisticRegression:
"""使用python实现逻辑回归算法"""
def __init__(self,alpha,times):
"""初始化方法:
Parameters:
----
alpah:float
学习率
times : int
迭代次数
"""
self.alpha = alpha
self.times = times
def sigmoid(self,z):
"""sigmoid函数的实现
Parameters:
----
z: float
自变量,值为:z = w.T * x
Return:
----
result:float,值为[0,1]之间
返回样本属于类别一的概率值,用于结果的预测
当s > 0.5(z>=0)时,判定为类别一,否则判定为类别0
"""
return 1.0 / (1.0 + np.exp(-z))
def fit(self, X, y):
"""根据训练数据,对模型进行训练
Parameters:
----
X : 类数组类型,形状[样本数量,特征数量]
待训练的样本的特征属性
y : 类数组类型。形状为[样本数量]
每个样本的目标值(标签)
"""
#将X,y转换成ndarray数组
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]
#计算概率值(判定结果一的概率值)
p = self.sigmoid(z)
#损失值,根据逻辑回归的目标函数,计算损失值。
#目标函数:J(w) = - sum(yi * log(s(zi)) + (1-yi) * log(1-s(zi)))【i从1到n】
cost = -np.sum((y * np.log(p)) + (1 - y) * np.log(1-p))
self.loss_.append(cost)
#更新权重,公式:权重(j) = 权重(j) + 学习率 * sum((y - s(zi))* xj)
self.w_[0] += self.w_[0] + self.alpha * np.sum(y - p)
self.w_[1:] += self.w_[1:] + self.alpha * np.dot(X.T,y-p)
def predict_proba(self,X):
"""根据参数传递的样本,对样本数据进行预测
Parameters
-----
X:类数组类型,形状为[样本数量,样本特征数量]
待测试样本的属性特征
Return
----
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):
"""根据参数传递的样本,对样本数据进行预测
Parameters:
----
X:类数组类型,形状[样本数量,特征数量]
待测试的样本特征(属性)
Returns:
-----
result: 数组类型
预测结果(分类值)
"""
return np.argmax(self.predict_proba(X),axis = 1)
#构建测试集与训练街
t0 = data[data['Species'] == 0]
t1 = data[data['Species'] == 1]
t0 = t0.sample(len(t0),random_state = 0)
t1 = t1.sample(len(t1),random_state = 0)
train_X = pd.concat([t0.iloc[:40,:-1],t1.iloc[:40,:-1]],axis = 0)
train_y = pd.concat([t0.iloc[:40,-1],t1.iloc[:40,-1]],axis = 0)
test_X = pd.concat([t0.iloc[40:,:-1],t1.iloc[40:,:-1]],axis = 0)
test_y = pd.concat([t0.iloc[40:,-1],t1.iloc[40:,-1]],axis = 0)
#鸢尾花特征列都在同一个数量级,这里可以不用标准化处理
lr = LogisticRegression(alpha=0.01,times=20)
lr.fit(train_X,train_y)
#预测概率值
display(lr.predict_proba(test_X))
#类别预测
result = lr.predict(test_X)
display(result)
#计算准确性
np.sum(result == test_y) / len(test_X)
#对计算结果进行可视化展示
import matplotlib as mpl
import matplotlib.pyplot as plt
#设置matplotlib 支持中文显示
mpl.rcParams['font.family'] = 'SimHei' #设置字体为黑体
mpl.rcParams['axes.unicode_minus'] = False #设置在中文字体是能够正常显示负号(“-”)
#设置画布大小
plt.figure(figsize=(8,8))
#绘制预测值
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--')