目录
一.逻辑回归概述
1.定义
逻辑回归是一种广义的线性回归分析模型,根据给定的自变量数据集估算事件发生的概率.虽然名字是回归,但实际属于分类问题,广泛用于二分类问题
2.基本原理
(1)线性组合:
逻辑回归模型的核心是使用一个线性组合来表示输入特征与权重(weights)的乘积
公式为 z = w 1 x 1 + w 2 x 2 + . . . + w n x n + b z = w_1x_1 + w_2x_2 +...+w_nx_n+b z=w1x1+w2x2+...+wnxn+b
其中
-
z 是线性组合的结果。
-
w1,w2,…,wnw1,w2,…,wn 是权重(weights)
-
x1,x2,…,xnx1,x2,…,xn 是输入特征。
-
b 是偏置项,也可以看作是权重,对应于特征为1的项。
通过一个非线性的激活函数(通常是Sigmoid函数)来转换这个线性组合的值
(2)sigmoid函数
公式为 f ( z ) = 1 1 + e − z f(z) = \frac{1}{1+e^{-z}} f(z)=1+e−z1
函数图像为
(3)概率解释
将线性结果代入Sigmoid函数中,进而得到一个范围在0~1之间的数值,输出值可以被解释为概率,以0.5为阈值即可分类,例如输出值小于0.5,为类别1,输出值大于0.5,为类别二
3.代价函数
逻辑回归的代价函数通常指的是对数损失函数,这个函数衡量的是模型的预测概率与真实标签之间的差异.
公式为
L ( y , p ) = − 1 N ∑ i = 1 N [ y i ⋅ log ( p i ) + ( 1 − y i ) ⋅ log ( 1 − p i ) ] L(y, p) = -\frac{1}{N} \sum_{i=1}^{N} [y_i \cdot \log(p_i) + (1 - y_i) \cdot \log(1 - p_i)] L(y,p)=−N1i=1∑N[yi⋅log(pi)+(1−yi)⋅log(1−pi)]
其中
-
N 是样本的总数。
-
yi 是第 i 个样本的真实标签,通常取值为0或1。
-
pi 是模型预测第 i 个样本为标签为1的概率。
4.优化算法
通常使用梯度下降(Gradient Descent):它通过计算代价函数相对于参数的梯度,并更新参数以减少代价函数的值。这个过程重复进行,直到找到局部最小值。
二.逻辑回归实现
1.数据集
以下为一部分数据集(完整数据放在末尾)
def data_set():#数据准备
fr = open(r"D:\1.txt")
features = []
labels = []
for line in fr.readlines():
temp = line.strip().split()
features.append([float(temp[0]),float(temp[1])])
labels.append(int(temp[2]))
return np.array(features),np.array(labels)
根据前两个特征分别为X1,X2,以下为画出的图像
2.sigmoid函数
根据sigmoid函数公式直接写出对应代码即可
def sigmoid(z):
return 1.0 / (1.0 + np.exp(-z))
3.计算损失函数梯度及梯度下降
通过迭代更新权重来最小化损失函数,每个特征的误差加权求和即为梯度(grad)
def cal_gradient(X, y, weights):#计算损失函数梯度
z = np.dot(X, weights)#算点积
h = sigmoid(z)#模型的预测值
grad = np.dot(X.T, (h - y)) / y.size#计算误差项和特征矩阵转置的点积,对每个特征的误差加权求和,就是每个特征的梯度,除以y的长度来确保梯度大小和样本数量无关
return grad
def grad_desc(X, y, initial_weights, learning_rate, iterations):#梯度下降,initial_weights代表初始权重,为0.learning_rate为学习率,即α.iterations为迭代次数
weights = initial_weights
costs = []
for i in range(iterations):
grad = cal_gradient(X, y, weights)
weights -= learning_rate * grad
cost1 = cost(X,y,weights)
costs.append(cost1)
return weights,costs
其中costs为后面损失函数要使用的数值
可以计算出最终的weights为(第一个数值为偏置值,之后两个分别为w1和w2)
4.计算损失函数
通过公式可以得到
L ( y , p ) = − 1 N ∑ i = 1 N [ y i ⋅ log ( p i ) + ( 1 − y i ) ⋅ log ( 1 − p i ) ] L(y, p) = -\frac{1}{N} \sum_{i=1}^{N} [y_i \cdot \log(p_i) + (1 - y_i) \cdot \log(1 - p_i)] L(y,p)=−N1i=1∑N[yi⋅log(pi)+(1−yi)⋅log(1−pi)]
def cost(X, y, weights):#对数损失函数
z = np.dot(X, weights)
h = sigmoid(z)
cost1 = -np.mean(y * np.log(h) + (1 - y) * np.log(1 - h))
return cost1
通过梯度下降,可以得到损失函数图像如下图
def draw_cost(costs):
plt.plot(costs)
plt.title('Cost vs. Iterations')
plt.xlabel('Iterations')
plt.ylabel('Cost')
plt.show()
代价函数越小,代表模型越好.通过梯度下降,可以看到代价函数逐步减小
5.结果
使用以下代码来测试
def draw_point(x,y):
x1 = []
y1 = []
x2 = []
y2 = []
for i in range(len(y)):
if y[i] == 0:
x1.append(x[i][0])
y1.append(x[i][1])
elif y[i] == 1:
x2.append(x[i][0])
y2.append(x[i][1])
plt.scatter(x1, y1, marker='^', c='b', label="不过0")
plt.scatter(x2, y2, marker='o', c='g', label="过1")
plt.show()
def plotBestFit(wei):
wei = np.mat(wei)
weights = wei.getA()
dataArr,labelMat=data_set()
n = np.shape(dataArr)[0]
xcord1 = []; ycord1 = []
xcord2 = []; ycord2 = []
for i in range(n):
if int(labelMat[i])== 1:
xcord1.append(dataArr[i,0]); ycord1.append(dataArr[i,1])
else:
xcord2.append(dataArr[i,0]); ycord2.append(dataArr[i,1])
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
ax.scatter(xcord2, ycord2, s=30, c='green')
x = np.arange(-3.0, 3.0, 0.1)
y = (-weights[0]-weights[1]*x)/weights[2]
ax.plot(x, y)
plt.xlabel('X1')
plt.ylabel('X2')
plt.show()
if __name__ == "__main__":
X,y = data_set()
draw_point(X, y)
X = np.hstack([np.ones((X.shape[0], 1)), X])#添加一列常数项1来拟合出截距项
initial_weights = np.zeros(X.shape[1])#初始化权重为0
learning_rate = 0.01#设置学习率,即α
iterations = 1000#设置次数
weights,costs = grad_desc(X, y, initial_weights, learning_rate, iterations)
plotBestFit(weights.reshape((3,1)))
最终得到的图为
可以计算一下准确率可得
6.预测
def predict(inX, weights):
prob = sigmoid(sum(inX * weights))
if prob > 0.5:
return 1.0
else:
return 0.0
X,y = data_set()
draw_point(X, y)
X = np.hstack([np.ones((X.shape[0], 1)), X])#添加一列常数项1来拟合出截距项
initial_weights = np.zeros(X.shape[1])#初始化权重为0
learning_rate = 0.01#设置学习率,即α
iterations = 1000#设置次数
weights,costs = grad_desc(X, y, initial_weights, learning_rate, iterations)
weight=[weights[0],weights[1],weights[2]]
inx = [1, -1.19, 3.44]
inx = np.array(inx)
print("该样本类别为:", predict(inx, weight))
三.总结
逻辑回归作为机器学习中的经典算法之一,在分类问题中扮演着重要角色。
核心概念
- Sigmoid函数
- 损失函数
- 梯度下降
局限性
尽管逻辑回归是一个简单而有效的算法,但它也有局限性例如,它假设特征与目标变量之间存在线性关系,这在现实世界的问题中并不总是成立。
优缺点
- 优点
1.易于理解和实现
2.适用于概率预测
3.快速计算
- 缺点
1.对特征的线性关系假设
2.分类阈值固定
3.忽略特征间的交互
总的来说,逻辑回归适用于许多分类问题,尤其是在特征与目标变量之间存在线性关系时。它也有局限性,需要根据具体问题和数据集的特点来决定是否使用逻辑回归,或者是否需要与其他机器学习技术结合使用。
附
完整数据集
0.12 0.34 0
1.23 4.56 1
0.98 2.34 0
1.45 3.67 1
2.22 1.11 0
3.33 4.44 1
0.55 0.66 0
1.78 2.89 1
2.56 3.21 1
0.31 0.42 0
1.11 2.22 1
0.45 0.78 0
2.34 3.45 1
1.67 2.98 1
0.22 0.33 0
3.21 4.32 1
1.23 0.45 0
2.11 3.22 1
0.56 0.78 0
1.34 2.56 1
3.45 4.67 1
0.12 1.23 0
2.34 3.45 1
0.67 0.89 0
1.23 3.45 1
0.98 1.23 0
3.21 4.56 1
1.11 0.22 0
2.33 3.44 1
0.55 0.66 0
1.78 2.89 1
2.34 3.21 1
0.31 0.42 0
1.11 2.22 1
0.45 0.78 0
2.34 3.45 1
1.67 2.98 1
0.22 0.33 0
3.21 4.32 1
1.23 0.45 0
2.11 3.22 1
0.56 0.78 0
1.34 2.56 1
3.45 4.67 1
0.12 1.23 0
2.34 3.45 1
0.67 0.89 0
1.23 3.45 1
0.98 1.23 0
3.21 4.56 1
1.11 0.22 0
2.33 3.44 1
0.55 0.66 0
1.78 2.89 1
2.56 3.21 1
0.31 0.42 0
1.11 2.22 1
0.45 0.78 0
2.34 3.45 1
1.67 2.98 1
0.22 0.33 0
3.21 4.32 1
1.23 0.45 0
2.11 3.22 1
0.56 0.78 0
1.34 2.56 1
3.45 4.67 1
0.12 1.23 0
2.34 3.45 1
0.67 0.89 0
1.23 3.45 1
0.98 1.23 0
3.21 4.56 1
1.11 0.22 0
2.33 3.44 1
0.55 0.66 0
1.78 2.89 1
2.56 3.21 1
0.31 0.42 0
1.11 2.22 1
0.45 0.78 0
2.34 3.45 1
1.67 2.98 1
0.22 0.33 0
3.21 4.32 1
1.23 0.45 0
2.11 3.22 1
0.56 0.78 0
1.34 2.56 1
3.45 4.67 1
0.12 1.23 0
2.34 3.45 1
0.67 0.89 0
1.23 3.45 1
0.98 1.23 0
3.21 4.56 1
1.11 0.22 0
2.33 3.44 1
0.42 0.56 0
1.89 3.12 1
0.34 0.89 0
2.45 3.67 1
1.22 0.99 0
3.78 4.56 1
0.61 0.73 0
1.57 2.23 1
2.89 3.45 1
0.21 0.34 0
1.45 2.67 1
0.56 0.78 0
2.34 3.45 1
1.89 2.98 1
0.33 0.45 0
3.67 4.32 1
1.12 0.34 0
2.56 3.78 1
0.78 0.99 0
1.34 2.45 1
3.23 4.56 1
0.23 0.45 0
2.67 3.89 1
0.89 0.12 0
1.56 3.45 1
0.98 1.45 0
3.45 4.78 1
1.22 0.67 0
2.78 3.56 1
0.45 0.56 0
1.89 2.67 1
2.67 3.45 1
0.34 0.45 0
1.12 2.34 1
0.56 0.67 0
2.78 3.89 1
1.45 2.56 1
0.34 0.45 0
3.45 4.56 1
1.12 0.34 0
-0.38 0.56 0
0.73 4.56 1
0.48 2.34 0
1.45 3.67 1
1.72 1.11 0
3.33 4.44 1
0.05 0.66 0
1.78 2.89 1
2.06 3.21 1
-0.19 0.42 0
0.61 2.22 1
-0.05 0.78 0
2.34 3.45 1
1.17 2.98 1
-0.28 0.33 0
3.21 4.32 1
-1.58 -0.56 0
-2.78 4.56 1
-2.67 2.34 0
-1.45 3.67 1
-2.34 1.11 0
-2.96 4.44 1
-2.53 0.66 0
-1.84 2.89 1
-2.45 3.21 1
-2.01 0.42 0
-2.64 2.22 1
-2.72 0.78 0
-1.91 3.45 1
-2.37 2.98 1
-2.83 0.33 0
-2.48 4.32 1
-1.98 -0.56 0
-0.83 4.56 1
-1.77 2.34 0
-0.65 3.67 1
-0.94 1.11 0
-0.91 4.44 1
-1.53 0.66 0
-0.85 2.89 1
-0.74 3.21 1
-0.99 0.42 0
-0.76 2.22 1
-0.87 0.78 0
-0.51 3.45 1
-0.73 2.98 1
-1.92 0.33 0
-0.61 4.32 1