逻辑回归----线性逻辑回归与非线性逻辑回归

线性逻辑回归

逻辑回归的预测函数

在这里插入图片描述

逻辑回归的代价函数

如果采用线性回归的代价函数的形式,随着自变量 θ \theta θ的变化将会出现很多的局部最小值(如下图左边所示),不适合使用梯度下降法求解参数。在这里插入图片描述
所以采用了如下代价函数:
在这里插入图片描述
所以,合并后的损失函数如下:
在这里插入图片描述
利用梯度下降法更新参数如下:
在这里插入图片描述

在这里插入图片描述

逻辑回归正则化:

在这里插入图片描述

python梯度下降法实现逻辑线性回归:

import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import classification_report
from sklearn import preprocessing

# 数据是否需要标准化
scale = False

# 载入数据
data = np.genfromtxt("LR-testSet.csv", delimiter=",")
x_data = data[:,:-1]# x_data含有两列,表示两个特征(这里表示坐标)
y_data = data[:,-1,np.newaxis]# y_data含有一列,表示一个结果
    
# 定义绘图函数
def plot():
    x0 = []
    x1 = []
    y0 = []
    y1 = []
    # 切分不同类别的数据
    for i in range(len(x_data)):
        if y_data[i]==0:# 是类别0则将他的两个特征分别加入x0,y0,这里的两个特征其实就是坐标
            x0.append(x_data[i,0])
            y0.append(x_data[i,1])
        else:# 是类别1则将他的两个特征分别加入x1,y1
            x1.append(x_data[i,0])
            y1.append(x_data[i,1])

    # 画图
    scatter0 = plt.scatter(x0, y0, c='b', marker='o')
    scatter1 = plt.scatter(x1, y1, c='r', marker='x')
    #画图例
    plt.legend(handles=[scatter0,scatter1],labels=['label0','label1'],loc='best')
   


# 给样本添加偏置项,添加一列1到第0列
X_data = np.concatenate((np.ones((100,1)),x_data),axis=1)


def sigmoid(x):#定义分类函数。可以传入一个(1,n)的矩阵,得到一个(1,n)的结果
    return 1.0/(1+np.exp(-x))


# 代价函数
def cost(xMat, yMat, ws):
    left = np.multiply(yMat, np.log(sigmoid(xMat*ws)))# (m,1)*((m,n)*(n,1))=(m,1)对于矩阵,*是矩阵相乘,multiply是对应位置相乘
    right = np.multiply(1 - yMat, np.log(1 - sigmoid(xMat*ws)))
    return np.sum(left + right) / -(len(xMat))# 将每一组的损失加起来求平均表示当前的平均损失 


# 梯度下降法,需要接受一个带有偏置的特征二维数组xArr和结果标签二维数组yArr
def gradAscent(xArr, yArr):
    if scale == True:
        xArr = preprocessing.scale(xArr) #数据集的标准化
       
    # 将数组转为矩阵方便下面矩阵计算
    xMat = np.mat(xArr)
    yMat = np.mat(yArr)

    #学习率和训练次数
    lr = 0.001
    epochs = 10000
    # 记录训练时的损失变化
    costList = []
    # 计算数据行列数,行代表数据个数,列代表权值个数
    m,n = np.shape(xMat)
    # 初始化权值,n行1列的矩阵,权值全为1
    ws = np.mat(np.ones((n,1)))
    
    for i in range(epochs+1):             
        # xMat和weights矩阵相乘
        h = sigmoid(xMat*ws)   #  根据当前权值计算一批结果(m,n)*(n,1)=(m,1)
        # 计算误差
        ws_grad = xMat.T*(h - yMat)/m  # 所有数据的某列特征×误差并求和然后求平均得些样本该特征得误差平均  (n,m)*(m,1)=(n,1)
        ws = ws - lr*ws_grad 
        
        if i % 50 == 0:# 每迭代50次记录一下误差
            costList.append(cost(xMat,yMat,ws))
    return ws,costList


# 训练模型,传入带有偏置的特征(100,3)和结果标签(100,1),得到一个(3,1)的系数矩阵和损失变化
ws,costList = gradAscent(X_data, y_data)

#如果是标准化的数据,不好画决策边界线 
if scale == False:
    # 画图决策边界
    plot()
    x_test = [[-4],[3]]#取两点确定一条直线
    y_test = (-ws[0] - x_test*ws[1])/ws[2]  #w0+w1X1+w2W2=0:此函数为sigmoid函数里面的那个θ^T X,为边界决策线。这里将X2看成Y
    plt.plot(x_test, y_test, 'k')
    plt.show()

# 画图 loss值的变化,在0-10000之间取201个点
x = np.linspace(0,10000,201)
plt.plot(x, costList, c='r')
plt.title('Train')
plt.xlabel('Epochs')
plt.ylabel('Cost')
plt.show()

# 预测
def predict(x_data, ws):
    if scale == True:
        x_data = preprocessing.scale(x_data)
    xMat = np.mat(x_data)
    ws = np.mat(ws)
    return [1 if x >= 0.5 else 0 for x in sigmoid(xMat*ws)]

predictions = predict(X_data, ws)

print(classification_report(y_data, predictions))

分割线:
在这里插入图片描述
随着训练次数的增加损失值的变化:
在这里插入图片描述
结果评估:
在这里插入图片描述
如果将scale改成True,即进行数据标准化,则有以下结果:
在这里插入图片描述
在这里插入图片描述
可见,数据标准化更有利于提高模型训练的准确度。

用sklearn实现逻辑线性回归:

import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import classification_report
from sklearn import preprocessing
from sklearn import linear_model
# 数据是否需要标准化
scale = False

# 载入数据
data = np.genfromtxt("LR-testSet.csv", delimiter=",")
x_data = data[:,:-1]
y_data = data[:,-1]
    
    
def plot():
    x0 = []
    x1 = []
    y0 = []
    y1 = []
    # 切分不同类别的数据
    for i in range(len(x_data)):
        if y_data[i]==0:
            x0.append(x_data[i,0])
            y0.append(x_data[i,1])
        else:
            x1.append(x_data[i,0])
            y1.append(x_data[i,1])

    # 画图
    scatter0 = plt.scatter(x0, y0, c='b', marker='o')
    scatter1 = plt.scatter(x1, y1, c='r', marker='x')
    #画图例
    plt.legend(handles=[scatter0,scatter1],labels=['label0','label1'],loc='best')


logistic = linear_model.LogisticRegression()
logistic.fit(x_data, y_data)

if scale == False:
    # 画图决策边界
    plot()
    x_test = np.array([[-4],[3]])
    y_test = (-logistic.intercept_ - x_test*logistic.coef_[0][0])/logistic.coef_[0][1]
    plt.plot(x_test, y_test, 'k')
    plt.show()
    
predictions = logistic.predict(x_data)
print(classification_report(y_data, predictions))

结果:
在这里插入图片描述
在这里插入图片描述

非线性逻辑回归

用python实现非线性逻辑回归

import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import classification_report
from sklearn import preprocessing
from sklearn.preprocessing import PolynomialFeatures
# 数据是否需要标准化
scale = False

# 载入数据
data = np.genfromtxt("LR-testSet2.txt", delimiter=",")
x_data = data[:,:-1]
y_data = data[:,-1,np.newaxis]
    
def plot():
    x0 = []
    x1 = []
    y0 = []
    y1 = []
    # 切分不同类别的数据
    for i in range(len(x_data)):
        if y_data[i]==0:
            x0.append(x_data[i,0])
            y0.append(x_data[i,1])
        else:
            x1.append(x_data[i,0])
            y1.append(x_data[i,1])

    # 画图
    scatter0 = plt.scatter(x0, y0, c='b', marker='o')
    scatter1 = plt.scatter(x1, y1, c='r', marker='x')
    #画图例
    plt.legend(handles=[scatter0,scatter1],labels=['label0','label1'],loc='best')

#进行特征的构造,构造的方式就是特征与特征相乘(自己与自己,自己与其他人),degree:控制多项式的最高次数;
poly_reg  = PolynomialFeatures(degree=3) 
# 特征处理
x_poly = poly_reg.fit_transform(x_data)# 会由原特征得出更多的特征,这是与线性逻辑回归不同的地方,degree=3时,原始的两个特征会组合成十个特征

def sigmoid(x):
    return 1.0/(1+np.exp(-x))

def cost(xMat, yMat, ws):
    left = np.multiply(yMat, np.log(sigmoid(xMat*ws)))
    right = np.multiply(1 - yMat, np.log(1 - sigmoid(xMat*ws)))
    return np.sum(left + right) / -(len(xMat))

def gradAscent(xArr, yArr):
    if scale == True:
        xArr = preprocessing.scale(xArr)
    xMat = np.mat(xArr)
    yMat = np.mat(yArr)
    
    lr = 0.03
    epochs = 50000
    costList = []
    # 计算数据列数,有几列就有几个权值
    m,n = np.shape(xMat)
    # 初始化权值
    ws = np.mat(np.ones((n,1)))
    
    for i in range(epochs+1):             
        # xMat和weights矩阵相乘
        h = sigmoid(xMat*ws)   
        # 计算误差
        ws_grad = xMat.T*(h - yMat)/m
        ws = ws - lr*ws_grad 
        
        if i % 50 == 0:
            costList.append(cost(xMat,yMat,ws))
    return ws,costList

# 训练模型,得到权值和cost值的变化,由于是非线性逻辑回归,且degree=3,所以原始的两个特征变成10个组合特征后,训练出的参数也是(10,1)的
ws,costList = gradAscent(x_poly, y_data)

# 获取数据值所在的范围
x_min, x_max = x_data[:, 0].min() - 1, x_data[:, 0].max() + 1
y_min, y_max = x_data[:, 1].min() - 1, x_data[:, 1].max() + 1

# 生成网格矩阵,间隔为0.02看起来就是连成一片。xx,yy的shape是一样的
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
                     np.arange(y_min, y_max, 0.02))

# np.r_按row来组合array, 
# np.c_按colunm来组合array
# >>> a = np.array([1,2,3])
# >>> b = np.array([5,2,5])

# >>> np.c_[a,b]
# array([[1, 5],
#        [2, 2],
#        [3, 5]])

# >>> np.r_[a,b]
# array([1, 2, 3, 5, 2, 5])


# ravel:多维数据转一维。
# np.c_[xx.ravel(), yy.ravel()]是(n,2),poly_reg.fit_transform(np.c_[xx.ravel(), yy.ravel()])是(n,10),因为degree为3。其中n=((x_max-x_min)/0.02)*((y_max-y_min)/0.02)
# 计算区域内每个点的sigmoid值
z = sigmoid(poly_reg.fit_transform(np.c_[xx.ravel(), yy.ravel()]).dot(np.array(ws)))#.dot表示矩阵乘法,(n,10)*(10,1)=(n,1)

# 将区域内的每一个点进行分类
for i in range(len(z)):
    if z[i] > 0.5:
        z[i] = 1
    else:
        z[i] = 0
        
z = z.reshape(xx.shape)

# 等高线图
plt.contourf(xx, yy, z)
plot() 
plt.show()

# 画图 loss值的变化,在0-50000之间取1001个点
x = np.linspace(0,50000,1001)
plt.plot(x, costList, c='r')
plt.title('Train')
plt.xlabel('Epochs')
plt.ylabel('Cost')
plt.show()

# 预测
def predict(x_data, ws):
    if scale == True:
        x_data = preprocessing.scale(x_data)
    xMat = np.mat(x_data)
    ws = np.mat(ws)
    return [1 if x >= 0.5 else 0 for x in sigmoid(xMat*ws)]

predictions = predict(x_poly, ws)
print(classification_report(y_data, predictions))

结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

用sklearn实现非线性逻辑回归

import numpy as np
import matplotlib.pyplot as plt
from sklearn import linear_model
from sklearn.datasets import make_gaussian_quantiles
from sklearn.preprocessing import PolynomialFeatures

#生成2维正态分布, x_data为样本特征,y_data为样本类别输出, 共200个样本,每个样本2个特征,输出有2个类别
x_data, y_data = make_gaussian_quantiles(n_samples=200, n_features=2,n_classes=2)

plt.scatter(x_data[:, 0], x_data[:, 1], c=y_data)
plt.show()

# 定义多项式回归,degree的值可以调节多项式的特征
poly_reg  = PolynomialFeatures(degree=5) 
# 特征处理
x_poly = poly_reg.fit_transform(x_data)
# 定义逻辑回归模型
logistic = linear_model.LogisticRegression()
# 训练模型
logistic.fit(x_poly, y_data)

# 获取数据值所在的范围
x_min, x_max = x_data[:, 0].min() - 1, x_data[:, 0].max() + 1
y_min, y_max = x_data[:, 1].min() - 1, x_data[:, 1].max() + 1

# 生成网格矩阵
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
                     np.arange(y_min, y_max, 0.02))

z = logistic.predict(poly_reg.fit_transform(np.c_[xx.ravel(), yy.ravel()]))
z = z.reshape(xx.shape)
# 等高线图
plt.contourf(xx, yy, z)
# 样本散点图
plt.scatter(x_data[:, 0], x_data[:, 1], c=y_data)
plt.show()

print('score:',logistic.score(x_poly,y_data))

结果:
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值