逻辑回归也被称为广义线性回归模型,与线性回归模型的形式基本上相同,最大的区别在于因变量不同。如果是连续的因变量,就是多重线性回归;如果是二项分布的因变量,就是逻辑(Logistic)回归。
这里主要说一下Logistic回归:
Logistic回归实际上是一种分类方法,主要用于二分类(注意是“主要”,不是仅)。Logistic回归的过程就是面对一个回归或者分类问题,建立代价函数,然后通过优化方法迭代求解出最优的模型参数,然后测试验证这个求解的模型的好坏。
优点:速度快,适合二分类问题;简单、容易理解;可以直接看到各个特征的权重,容易更新模型吸收新的数据。
缺点:对数据和场景的适应能力有局限性,不如决策树算法适应性强。
用途:1、寻找危险因素:寻找某一疾病的危险因素等;2、预测:根据模型,预测在不同的自变量情况下,发生某种疾病或属于某种情况的概率有多;3、判别:实际上跟预测有些类似,也是根据模型,判断某种疾病或属于某种情况的概率有多大。
步骤:寻找预测函数h,构造损失函数J,想办法使得损失函数J最小并求得回归参数.
二分类问题的概率与自变量之间的关系图形往往是一个如下所示的S型曲线,可用sigmoid函数(其实就是Logistic函数)表示,即
在多元线性回归中,一般采用最小二乘法来进行参数估计;相对应的,在逻辑回归中,一般采用最大似然法来进行参数估计。其基本原理是:找到一组参数,可以让样本数据所包含的观察值被观察到的可能性最大。最大似然法的优点是大样本数据中的参数的估计稳定、偏差小、估计方差小。
现采用极大似然法来求解损失函数:
上面已经将求解最大值问题转化为求解最小值问题,用梯度下降法求解 更新公式:
a相当于步长l
对于逻辑回归就是相当于引入了基函数让线性回归模型变得更加灵活,但是也很容易造成过拟合。对于过拟合问题可以采用正则化解决,正则化是结构风险最小化策略的实现,是在经验风险上加一个正则化项或惩罚项。正则化项一般是模型复杂的单调递增函数,模型越复杂,正则化项就越大。 正则化后现在的模型的损失函数可表示为:
(说实话,这里就没利用上面向量化的结果,不太清楚这个是怎么来的)
为正则化系数。如果它很大,则表示对模型的复杂度惩罚大,对拟合数据的损失惩罚小,这样就不会造成过分拟合数据,在训练数据上的偏差较大,在未知数据上的方差较小,但是可能出现欠拟合的现象;如果它很小,则说明比较注重对训练数据的拟合,在训练数据上的偏差会比较小,但是可能会导致过拟合。
正则化后的梯度下降算法回归系数的更新变为:
描述就容易解释了,在(0,1)区间,导数为正数,更新的x在增大,一直向最高点逼近;同样在(1,2)区间,导数为负数,更新的x描述在减小,一直向最高点逼近
描述就容易解释了,在(-2,-1)区间,导数为负数,更新的x在增大,一直向最低点逼近;同样在(-1,-2)区间,导数为正数,更新的x在减小,一直向最低点逼近。
但是一般情况下我们求解最大值不是用梯度上升法,而是利用公式
将梯度上升问题转化为梯度下降的问题
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
'''
处理原始数据:将文本数据读入,变成我们想要的数据集
'''
def parse_data():
data = np.loadtxt('./data0.txt')
dataMat = data[:, 0:-1]
#最后一列是0,1标签列
classLabels = data[:, -1]
dataMat = np.insert(dataMat, 0, 1, axis=1)
return dataMat, classLabels
'''
定义sigmod函数
'''
def sigmoid(x):
return 1 / (1 + np.exp(-x))
'''
定义损失函数
'''
def loss_funtion(dataMat, classLabels, weights):
m, n = np.shape(dataMat)
loss = 0.0
for i in range(m):
sum_theta_x = 0.0
sum_theta_x = int(dataMat[i] * weights)
# for j in range(n):
# sum_theta_x += dataMat[i, j] * weights.T[0, j]
propability = sigmoid(sum_theta_x)
#其实这里是根据公式来的,这里比这公式里少了一个1/m
#(-1/m) * np.sum((np.multiply(y, np.log(y_pred)) + np.multiply((1-y),np.log(1-y_pred))))
loss += -classLabels[i, 0] * np.log(propability) - (1 - classLabels[i, 0]) * np.log(1 - propability)
return loss
#计算权重
def grad_descent(dataMatIn, classLabels):
dataMatrix = np.mat(dataMatIn) #(m,n)
labelMat = np.mat(classLabels).T
m, n = np.shape(dataMatrix)
weights = np.ones((n, 1))
alpha = 0.01
maxstep = 10000 #循环次数
eps = 0.0001 #设定的一个阈值
count = 0
loss_array = []
for i in range(maxstep):
#先计算开始的损失
loss = loss_funtion(dataMatrix, labelMat, weights)
h_theta_x = sigmoid(dataMatrix * weights)
#误差
e = h_theta_x - labelMat
#更新的权重
new_weights = weights - alpha * dataMatrix.T * e
#根据新更新的权重获取新的损失值
new_loss = loss_funtion(dataMatrix, labelMat, new_weights)
loss_array.append(new_loss)
#更新前后损失值无太大差别,则不再循环求取权重
if abs(new_loss - loss) < eps:
break
else: #否则的话继续更新权重,直至达到最有循环数
weights = new_weights
count += 1
print ("count is: ", count) #循环进行次数
#print ("loss is: ", loss)
print ("weights is: ", weights) #最终获取的权重值
return weights, loss_array
#画出损失值收敛过程
def plotloss(loss_array):
n = len(loss_array)
plt.xlabel("iteration num")
plt.ylabel("loss")
plt.scatter(range(1, n+1), loss_array)
plt.show()
data, labels = parse_data()
r, loss_array = grad_descent(data, labels)
r = np.mat(r).transpose()
plotloss(loss_array)
#坐标轴,画出边界
w = r.T
x = np.arange(-3.0,3.0,0.1)
x1 = list()
for i in x:
x1.append([i])
y = (-w[0]-x1*w[1])/w[2]
plt.scatter(data[:,1],data[:,2],c=labels)
plt.plot(x,y)
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
data = np.loadtxt('./data0.txt')
x = data[:,(0,1)]
y = data[:,2]
X_train, X_test, Y_train, Y_test = train_test_split(x, y, test_size=0.3, random_state=0)
log_reg = LogisticRegression()
log_reg.fit(X_train, Y_train)
test_data_proba = log_reg.predict(X_test)
#模型准确率
accuracy = accuracy_score(Y_test,test_data_proba)
print('模型准确率:',accuracy)
x_plot = np.arange(-3.0,3.0,0.1)
x1 = list()
for i in x_plot:
x1.append([i])
log_reg_coef = np.mat(log_reg.coef_).T
log_reg_intercept = np.mat(log_reg.intercept_)
y_plot = (- log_reg_intercept[0]- x1*log_reg_coef[0])/log_reg_coef[1]
plt.plot(x_plot,y_plot)
labels = data[:,2]
plt.scatter(data[:,0],data[:,1],c=labels)