欢迎关注 『机器学习』 系列,持续更新中
欢迎关注 『机器学习』 系列,持续更新中
上次线性回归手搓代码实现太花时间,也收到大家的反馈要求,这次我们不自己从头造轮子,站在前人的肩膀上,使用sklearn库实现逻辑回归。代码更加简明。
w3cschool学习sklearn库api方法
拿来即用,所见即所得。
项目仓库:https://gitee.com/miao-zehao/machine-learning/tree/master
题目要求:A、数据集的处理。给的数据集的文件Iris.csv,将文件格式转换为dat文件格式(Iris-x.dat, Iris-y.dat),以便使用例子代码中的相应语句导入数据集。注意:两个标签种类,将标签值(setosa、versicolor)分别转换为0、1,以便后续处理。
常规的做法,大体使用pandas读取csv文件数据。
setosa
和versicolor
转化为0
和1
#1.把第五个y值改成1或0
for i in range(len(data)):
if data[i,4]=='setosa':
data[i,4]=1
elif data[i,4]=='versicolor':
data[i,4]=0
#2.数据归一化
max_abs_scaler = preprocessing.MaxAbsScaler()#注册一个预处理对象
data = max_abs_scaler.fit_transform(data)#fit_transform(X[, y]) 适合数据,然后转换它。
#3.切片取得特征值和分类标记
Iris_X=data[:,0:4]#取得前面的4个特征值
print(Iris_X)
Iris_Y=data[:,4].astype('int')#取得第五个分类结果,用1和0表示
#注意一定要让y值加上.astype('int'),否则会报错,对于标本结果必须要是整型。
print(Iris_Y)
#4.保存数据到dat文件中
pd.DataFrame(Iris_X).to_csv('Iris_X.dat')
pd.DataFrame(Iris_Y).to_csv('Iris_Y.dat')
完整数据处理代码如下:
import pandas as pd
import numpy as np
from sklearn import preprocessing
data=pd.read_csv("Iris.csv").values
#1.把第五个y值改成1或0
for i in range(len(data)):
if data[i,4]=='setosa':
data[i,4]=1
elif data[i,4]=='versicolor':
data[i,4]=0
#2.数据归一化
max_abs_scaler = preprocessing.MaxAbsScaler()#注册一个预处理对象
data = max_abs_scaler.fit_transform(data)#fit_transform(X[, y]) 适合数据,然后转换它。
#3.切片取得特征值和分类标记
Iris_X=data[:,0:4]#取得前面的4个特征值
print(Iris_X)
Iris_Y=data[:,4].astype('int')#取得第五个分类结果,用1和0表示
#注意一定要让y值加上.astype('int'),否则会报错,对于标本结果必须要是整型。
print(Iris_Y)
#4.保存数据到dat文件中
pd.DataFrame(Iris_X).to_csv('Iris_X.dat')
pd.DataFrame(Iris_Y).to_csv('Iris_Y.dat')
函数封装代码如下:
import pandas as pd
import numpy as np
from sklearn import preprocessing
def load_data():
data=pd.read_csv("Iris.csv").values
#1.把第五个y值改成1或0
for i in range(len(data)):
if data[i,4]=='setosa':
data[i,4]=1
elif data[i,4]=='versicolor':
data[i,4]=0
#2.数据归一化
max_abs_scaler = preprocessing.MaxAbsScaler()#注册一个预处理对象
data = max_abs_scaler.fit_transform(data)#fit_transform(X[, y]) 适合数据,然后转换它。
#3.切片取得特征值和分类标记
Iris_X=data[:,0:4]#取得前面的4个特征值
Iris_Y=data[:,4]#取得第五个分类结果,用1和0表示
return Iris_X,Iris_Y.astype('int')#注意一定要让y值加上.astype('int'),否则会报错,对于标本结果必须要是整型。
题目要求:B、选择第一个和第三个特征,作为训练模型使用的特征。画出二维数据图。
data_point=data[:,0:5:2]#取得x1,x3,y,这里用到了切片步长,刚刚好1,3,5步长2的切片
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from prettytable import PrettyTable
from sklearn import preprocessing
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.model_selection import train_test_split
def load_data():
data=pd.read_csv("Iris.csv").values
#1.把第五个y值改成1或0
for i in range(len(data)):
if data[i,4]=='setosa':
data[i,4]=1
elif data[i,4]=='versicolor':
data[i,4]=0
#2.数据归一化
max_abs_scaler = preprocessing.MaxAbsScaler()#注册一个预处理对象
data = max_abs_scaler.fit_transform(data)#fit_transform(X[, y]) 适合数据,然后转换它。
#3.切片取得特征值和分类标记
Iris_X=data[:,0:4]#取得前面的4个特征值
Iris_Y=data[:,4]#取得第五个分类结果,用1和0表示
return Iris_X,Iris_Y.astype('int')#注意一定要让y值加上.astype('int'),否则会报错,对于标本结果必须要是整型。
#1.读取数据
Iris_X,Iris_Y=load_data()
#把两类数据分类
arry_1=[]
arry_0=[]
for i in range(len(Iris_X)):
if Iris_Y[i]==1:
arry_1.append(Iris_X[i])
elif Iris_Y[i]==0:
arry_0.append(Iris_X[i])
arry_1=np.array(arry_1)
arry_0=np.array(arry_0)
#2.绘制散点图
plt.rcParams["font.sans-serif"]=["SimHei"] #用来正常显示中文标签
plt.title("分类散点图图")
plt.xlabel("特征1")
plt.ylabel("特征3")
#绘制散点图:scatter
plt.scatter(arry_1[:,0],arry_1[:,1],label='1',marker = "x")
plt.scatter(arry_0[:,0],arry_0[:,1],label='1',marker = "o")
#绘制标签
plt.legend(['setosa','versicolor'], loc=2, fontsize=10)
plt.savefig("B.二维数据图.png")
plt.show()
这一环节用到了很多的函数方法,使用前人造好的轮子确实方便高效。
(1)train_test_split()是交叉验证中常用的数据分割函数,可以把样本中随机的按比例选取train data和testdata
示例:X_train, X_test, y_train, y_test = train_test_split(Iris_X, np.ravel(Iris_Y),test_size=0.2,random_state=0)#导入数据,test_size=0.2表示训练和测试数据比例为8:2,为了保证每次结果的一致性而把随机数种子设置为0
(2)np.ravel(Iris_Y) 将多维数组降为一维,返回的是视图,修改时会影响原始矩阵
简单的一个例子来说就是像这样[[1 , 2] , [3 , 4]]—> [1 2 3 4],去掉了内部的括号
(3)LogisticRegression 逻辑回归求解函数
示例:reg = LogisticRegression(C=1e5, solver=‘newton-cg’,max_iter=1000,fit_intercept=True)
C:浮动,默认值:1.0 正则化强度的倒数;必须是正浮点数。与支持向量机一样,较小的值指定更强的正则化
。正则化越强,那么惩罚就越大。
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from prettytable import PrettyTable
from sklearn import preprocessing
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.model_selection import train_test_split
def load_data():
data=pd.read_csv("Iris.csv").values
#1.把第五个y值改成1或0
for i in range(len(data)):
if data[i,4]=='setosa':
data[i,4]=1
elif data[i,4]=='versicolor':
data[i,4]=0
#2.数据归一化
max_abs_scaler = preprocessing.MaxAbsScaler()#注册一个预处理对象
data = max_abs_scaler.fit_transform(data)#fit_transform(X[, y]) 适合数据,然后转换它。
#3.切片取得特征值和分类标记
data_point = data[:, 0:5:2] # 取得x1,x3,y,这里用到了切片步长,刚刚好1,3,5步长2的切片
Iris_X=data_point[:,0:2]#取得x1,x3
Iris_Y=data_point[:,2]#取得y,用1和0表示
return Iris_X,Iris_Y.astype('int')#注意一定要让y值加上.astype('int'),否则会报错,对于标本结果必须要是整型。
#1.读取数据
Iris_X,Iris_Y=load_data()
#2.导入数据,test_size=0.2表示训练和测试数据比例为8:2,为了保证每次结果的一致性而把随机数种子设置为0
X_train, X_test, y_train, y_test = train_test_split(Iris_X, np.ravel(Iris_Y),test_size=0.2,random_state=0)
#(1)train_test_split()是交叉验证中常用的数据分割函数,可以把样本中随机的按比例选取train data和testdata
#train_data:所要划分的样本特征集
#train_target:所要划分的样本结果
#test_size:样本占比,如果是整数的话就是样本的数量
#random_state:是随机数的种子。
#(2)np.ravel(Iris_Y) 将多维数组降为一维,返回的是视图,修改时会影响原始矩阵
#简单的一个例子来说就是像这样[[1 , 2] , [3 , 4]]---> [1 2 3 4],去掉了内部的括号
reg = LogisticRegression(C=1e5, solver='newton-cg',max_iter=1000,fit_intercept=True)
#(3)LogisticRegression 逻辑回归求解函数
#C:浮动,默认值:1.0 正则化强度的倒数;必须是正浮点数。与支持向量机一样,较小的值指定更强的正则化。
#solver:是选择求解器{'newton-cg','lbfgs','liblinear','sag'},默认值:'liblinear'
# liblinear:使用了开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数。
# lbfgs:拟牛顿法的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。
# newton-cg:也是牛顿法家族的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。
# sag:即随机平均梯度下降,是梯度下降法的变种,和普通梯度下降法的区别是每次迭代仅仅用一部分的样本来计算梯度,适合于样本数据多的时候。
# saga:线性收敛的随机优化算法的的变重。
#max_iter:整数,默认值:100仅对 newton-cg、sag 和 lbfgs 求解器有用。求解器收敛的最大迭代次数。
#fit_intercept:布尔值,默认值 真:指定是否应将常数(也称为偏差或截距)添加到决策函数中。
#3.训练模型
reg.fit(X_train,y_train)
#reg.fit,参数是样本特征集和样本结果集,X_train和y_train
#4.测试模型
y_pred=reg.predict(X_test)
print('test accuracy:\n',accuracy_score(y_test,y_pred)) #打印模型精度
print('weights:\n', reg.coef_, '\nbias:\n', reg.intercept_) #打印模型参数
pre=reg.predict(Iris_X)#使用特征x预测结果y
cm = confusion_matrix(Iris_Y, pre)#计算混淆矩阵
print("confusion_matrix:") #打印混淆矩阵
cm_table = PrettyTable(["","predict: 0 class", "predict: 1 class"])#格式化输出
cm_table.add_row(["true: 0 class",cm[0,0], cm[0,1]]);cm_table.add_row(["true: 1 class",cm[1,0], cm[1,1]])
print(cm_table)
其实这个模型精度1.0是让我犹豫再三的,我也咨询了课任老师,从老师处得知在模型数据差异性很大的情况下,是有可能出现这种精度1.0情况的。
如果把迭代次数设置为1,那么准确率不是1.0,但是一旦设置为迭代次数为2,模型精度直接变成了1.0,可见这次提供的数据集数据差异性确实很大,导致模型训练的效果很好。
与C题相比,核心在于封装一个有参数C的函数
def C_test(C):
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from prettytable import PrettyTable
from sklearn import preprocessing
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.model_selection import train_test_split
def load_data():
data=pd.read_csv("Iris.csv").values
#1.把第五个y值改成1或0
for i in range(len(data)):
if data[i,4]=='setosa':
data[i,4]=1
elif data[i,4]=='versicolor':
data[i,4]=0
#2.数据归一化
max_abs_scaler = preprocessing.MaxAbsScaler()#注册一个预处理对象
data = max_abs_scaler.fit_transform(data)#fit_transform(X[, y]) 适合数据,然后转换它。
#3.切片取得特征值和分类标记
data_point = data[:, 0:5:2] # 取得x1,x3,y,这里用到了切片步长,刚刚好1,3,5步长2的切片
Iris_X=data_point[:,0:2]#取得x1,x3
Iris_Y=data_point[:,2]#取得y,用1和0表示
return Iris_X,Iris_Y.astype('int')#注意一定要让y值加上.astype('int'),否则会报错,对于标本结果必须要是整型。
#1.读取数据
Iris_X,Iris_Y=load_data()
#我们把整个训练过程封装成一个函数,设置正则化指数C为函数参数,借助for循环
#(注意这里的C=1e5表示 C=1*10^5,而且C越大,正则化强度越小)
def C_test(C):
# 2.导入数据,test_size=0.2表示训练和测试数据比例为8:2,为了保证每次结果的一致性而把随机数种子设置为0
X_train, X_test, y_train, y_test = train_test_split(Iris_X, np.ravel(Iris_Y), test_size=0.2, random_state=0)
# (1)train_test_split()是交叉验证中常用的数据分割函数,可以把样本中随机的按比例选取train data和testdata
# train_data:所要划分的样本特征集
# train_target:所要划分的样本结果
# test_size:样本占比,如果是整数的话就是样本的数量
# random_state:是随机数的种子。
# (2)np.ravel(Iris_Y) 将多维数组降为一维,返回的是视图,修改时会影响原始矩阵
# 简单的一个例子来说就是像这样[[1 , 2] , [3 , 4]]---> [1 2 3 4],去掉了内部的括号
reg = LogisticRegression(C=C, solver='newton-cg', max_iter=1000, fit_intercept=True)
# (3)LogisticRegression 逻辑回归求解函数
# C:浮动,默认值:1.0 正则化强度的倒数;必须是正浮点数。与支持向量机一样,较小的值指定更强的正则化。
# solver:是选择求解器{'newton-cg','lbfgs','liblinear','sag'},默认值:'liblinear'
# liblinear:使用了开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数。
# lbfgs:拟牛顿法的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。
# newton-cg:也是牛顿法家族的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。
# sag:即随机平均梯度下降,是梯度下降法的变种,和普通梯度下降法的区别是每次迭代仅仅用一部分的样本来计算梯度,适合于样本数据多的时候。
# saga:线性收敛的随机优化算法的的变重。
# max_iter:整数,默认值:100仅对 newton-cg、sag 和 lbfgs 求解器有用。求解器收敛的最大迭代次数。
# fit_intercept:布尔值,默认值 真:指定是否应将常数(也称为偏差或截距)添加到决策函数中。
# 3.训练模型
reg.fit(X_train, y_train)
# reg.fit,参数是样本特征集和样本结果集,X_train和y_train
# 4.测试模型
y_pred = reg.predict(X_test)
print("--------------------------------")
print('this C:',C,'test accuracy:', accuracy_score(y_test, y_pred)) # 打印模型精度
print('weights:\n', reg.coef_, '\nbias:\n', reg.intercept_) #打印模型参数
for i in range(0,5):
C_test(1*(10**i))#在C成指数增长时,模型精度的变化
正则项存在的初衷是为了防止过拟合的发生,正则项越大表明惩罚力度越大,等于0表示不做惩罚。
在观察上图数据变化的过程中,我们发现随着C逐渐变大,正则化项逐渐变小,偏置项bias逐渐变大,而weights权重项逐渐变小。
根据归一化后的数据范围,生成队列数据,利用训练的模型生成预测值,然后绘制等高线分界线图。
分界线绘制核心代码:
#6.绘制分界线 Iris_X,Iris_Y
#xx, yy是绘图网格,所有数据的范围
xx, yy = np.meshgrid(np.arange(0.6, 1+0.01, 0.01),np.arange(0.2, 1+0.01, 0.01))#生成队列网格,这个范围根据前面B题生成图的x和y的范围大小最大值和最小值决定Z = reg.predict(np.c_[xx.ravel(), yy.ravel()])#合并网格
Z = Z.reshape(xx.shape)#改变网格形状
plt.contourf(xx, yy, Z, cmap=plt.cm.Paired)
plt.axis('tight')#'tight'刻度紧凑显示模式,设置足够大的限制以显示所有数据,然后禁用进一步的自动标度。
plt.title("逻辑回归分界线")
plt.xlabel("特征1")
plt.ylabel("特征3")
colors = "br"
for i, color in zip(reg.classes_, colors):
idx = np.where(Iris_Y == i)
plt.scatter(Iris_X[idx, 0], Iris_X[idx, 1], c=color, cmap=plt.cm.Paired,
edgecolor='black', s=20)
完整代码:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from prettytable import PrettyTable
from sklearn import preprocessing
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.model_selection import train_test_split
def load_data():
data=pd.read_csv("Iris.csv").values
#1.把第五个y值改成1或0
for i in range(len(data)):
if data[i,4]=='setosa':
data[i,4]=1
elif data[i,4]=='versicolor':
data[i,4]=0
#2.数据归一化
max_abs_scaler = preprocessing.MaxAbsScaler()#注册一个预处理对象
data = max_abs_scaler.fit_transform(data)#fit_transform(Iris_X[, y]) 适合数据,然后转换它。
#3.切片取得特征值和分类标记
data_point = data[:, 0:5:2] # 取得x1,x3,y,这里用到了切片步长,刚刚好1,3,5步长2的切片
Iris_X=data_point[:,0:2]#取得x1,x3
Iris_Y=data_point[:,2]#取得y,用1和0表示
return Iris_X,Iris_Y.astype('int')#注意一定要让y值加上.astype('int'),否则会报错,对于标本结果必须要是整型。
#1.读取数据
Iris_X,Iris_Y=load_data()
#2.导入数据,test_size=0.2表示训练和测试数据比例为8:2,为了保证每次结果的一致性而把随机数种子设置为0
X_train, X_test, y_train, y_test = train_test_split(Iris_X, np.ravel(Iris_Y),test_size=0.2,random_state=0)
#(1)train_test_split()是交叉验证中常用的数据分割函数,可以把样本中随机的按比例选取train data和testdata
#train_data:所要划分的样本特征集
#train_target:所要划分的样本结果
#test_size:样本占比,如果是整数的话就是样本的数量
#random_state:是随机数的种子。
#(2)np.ravel(Iris_Y) 将多维数组降为一维,返回的是视图,修改时会影响原始矩阵
#简单的一个例子来说就是像这样[[1 , 2] , [3 , 4]]---> [1 2 3 4],去掉了内部的括号
reg = LogisticRegression(C=1e5, solver='newton-cg',max_iter=1000,fit_intercept=True)
#(3)LogisticRegression 逻辑回归求解函数
#C:浮动,默认值:1.0 正则化强度的倒数;必须是正浮点数。与支持向量机一样,较小的值指定更强的正则化。
#solver:是选择求解器{'newton-cg','lbfgs','liblinear','sag'},默认值:'liblinear'
# liblinear:使用了开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数。
# lbfgs:拟牛顿法的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。
# newton-cg:也是牛顿法家族的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。
# sag:即随机平均梯度下降,是梯度下降法的变种,和普通梯度下降法的区别是每次迭代仅仅用一部分的样本来计算梯度,适合于样本数据多的时候。
# saga:线性收敛的随机优化算法的的变重。
#max_iter:整数,默认值:100仅对 newton-cg、sag 和 lbfgs 求解器有用。求解器收敛的最大迭代次数。
#fit_intercept:布尔值,默认值 真:指定是否应将常数(也称为偏差或截距)添加到决策函数中。
#3.训练模型
reg.fit(X_train,y_train.astype('int'))
#reg.fit,参数是样本特征集和样本结果集,X_train和y_train
#4.测试模型
y_pred=reg.predict(X_test)
print('test accuracy:\n',accuracy_score(y_test,y_pred)) #打印模型精度
print('weights:\n', reg.coef_, '\nbias:\n', reg.intercept_) #打印模型参数
pre=reg.predict(Iris_X)#使用特征x预测结果y
cm = confusion_matrix(Iris_Y, pre)#计算混淆矩阵
print("confusion_matrix:") #打印混淆矩阵
cm_table = PrettyTable(["","predict: 0 class", "predict: 1 class"])#格式化输出
cm_table.add_row(["true: 0 class",cm[0,0], cm[0,1]]);cm_table.add_row(["true: 1 class",cm[1,0], cm[1,1]])
print(cm_table)
#5.绘制散点
arry_1=[]
arry_0=[]
for i in range(len(Iris_X)):
if Iris_Y[i]==1:
arry_1.append(Iris_X[i])
elif Iris_Y[i]==0:
arry_0.append(Iris_X[i])
arry_1=np.array(arry_1)
arry_0=np.array(arry_0)
plt.rcParams["font.sans-serif"]=["SimHei"] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
#6.绘制分界线 Iris_X,Iris_Y
#xx, yy是绘图网格,所有数据的范围
xx, yy = np.meshgrid(np.arange(0.6, 1+0.01, 0.01),np.arange(0.2, 1+0.01, 0.01))#生成队列网格,这个范围根据前面B题生成图的x和y的范围大小最大值和最小值决定
Z = reg.predict(np.c_[xx.ravel(), yy.ravel()])#合并网格
Z = Z.reshape(xx.shape)#改变网格形状
plt.contourf(xx, yy, Z, cmap=plt.cm.Paired)
plt.axis('tight')#'tight'刻度紧凑显示模式,设置足够大的限制以显示所有数据,然后禁用进一步的自动标度。
plt.scatter(arry_1[:,0],arry_1[:,1],label='setosa',marker = "x")
plt.scatter(arry_0[:,0],arry_0[:,1],label='versicolor',marker = "o")
plt.title("逻辑回归分界线")
plt.xlabel("特征1")
plt.ylabel("特征3")
mylegend =plt.legend(['setosa','versicolor'], loc=2, fontsize=10)
frame = mylegend.get_frame()
frame.set_facecolor('white')
colors = "br"
for i, color in zip(reg.classes_, colors):
idx = np.where(Iris_Y == i)
plt.scatter(Iris_X[idx, 0], Iris_X[idx, 1], c=color, cmap=plt.cm.Paired,
edgecolor='black', s=20)
#7.保存图片
plt.savefig("E.画出决策分界线.png")
plt.show()
大家喜欢的话,给个,点个关注!给大家分享更多有趣好玩的python机器学习知识!
版权声明:
发现你走远了@mzh原创作品,转载必须标注原文链接
Copyright 2022 mzh
Crated:2022-9-15
欢迎关注 『机器学习』 系列,持续更新中
欢迎关注 『机器学习』 系列,持续更新中
【机器学习】01. 波士顿房价为例子学习线性回归
【机器学习】02. 使用sklearn库牛顿化、正则化的逻辑回归
【机器学习】03. 支持向量机SVM库进行可视化分类
【更多内容敬请期待】