赞
踩
目录
逻辑回归(Logistic Regression)是一种分类方法,虽然是命中中不带有分类二字但逻辑回归是应用最为广泛的二分类模型,逻辑回归通过引入Sigmoid函数将线性回归的预测值映射到[0, 1]区间内回归线性分类器。
例如,天色越黑,下雨概率就越大。即值越大,属于某类别的概率也越大。值与概率之间可以互转。
设平面上的样本,正例标记为1,负例标记为0,逻辑回归模型需要预测样本的标记值,也就是预测未知的样本x,是正例还是负例。
一般来说我们希望逻辑回归的预测结果g(x)的取值范围在[0,1],这样就可以看作是样本x属于某个类别的概率,当g趋近于1时,样本就更可能是正例,当g趋近于0时,样本就更可能是负例。
从而引入sigmoid函数。
Sigmoid函数的形式为:
其中,z 是线性回归的预测值。Sigmoid函数将z 映射到0和1之间,从而表示正类(通常是1)和负类(通常是0)的概率。
图像如下:
梯度表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(梯度的方向)变化最快,变化率(梯度的模)最大,可理解为导数。
梯度上升和梯度下降是优化算法中常用的两种方法,主要目的是通过迭代找到目标函数的最大值和最小值。
例如:
想象我们在一座很高的山上,怎么才能以最快的速度下山?我们可以先选择坡度最倾斜的方向走一段距离,然后再重新选择坡度最倾斜的方向,再走一段距离。以此类推,我们就可以以最快的速度到达山底。(梯度的方向,就是我们要选择的方向)
我们要得到的是方差最大的数据,即:
由于我们进行过数据的预处理。所以我们的目标就变为了:
映射关系推导
假设xi要映射到新的坐标轴上
在这里我们假设向量w为单位向量
则使之变为:
将映射关系带入
带入映射关系后我们的目标变为了
梯度上升
构建一个函数
现在我们构建一个函数
求导
下面我们开始对f(w)求导
我们的问题就变成了使用上述式子进行梯度上升,接下来我们使用梯度上升的方式优化w,优化得到的w即为可以将数据转换到方差更大的坐标轴上的主成分。
通过这些知识我可以实现一个简单的关于逻辑回归算法的实验,如下
- if __name__=='__main__':
- # 输出训练集和测试集
- # 使用make blobs函数,在平面上生成60个随机样本包含两个类别
- x, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.5)
- x_with_intercept = np.c_[np.ones((x.shape[0], 1)), x]
-
- # 分离出训练集和测试集
- x_train, y_train = x[:50], y[:50]
- x_test, y_test = x[50:], y[50:]
- print("训练集样本:")
- for i in range(len(x_train)):
- print(f"样本 {i+1} - 特征: {x_train[i]}, 标签: {y_train[i]}")
-
- print("\n测试集样本:")
- for i in range(len(x_test)):
- print(f"样本 {i+1} - 特征: {x_test[i]}, 真实标签: {y_test[i]}")
我们将样本输出看看
- # 定义sigmoid函数
- def sigmoid(z):
- return 1 / (1 + np.exp(-z))
- # 定义梯度上升算法
- def tdss(x, y, alpha=0.01, num_iterations=1000):
- m, n = x.shape
- weights = np.zeros(n)
-
- for _ in range(num_iterations):
- z = np.dot(x, weights)
- h = sigmoid(z)
- error = y - h
- gradient = np.dot(x.T, error) / m
- weights += alpha * gradient
-
- return weights
- # 绘制散点图和决策边界
- plt.scatter(x[y == 1, 0], x[y == 1, 1], color='blue', marker='o', label='label1')
- plt.scatter(x[y == 0, 0], x[y == 0, 1], color='red', marker='s', label='label0')
-
- x_decision = np.array([np.min(x[:, 0]), np.max(x[:, 0])])
- y_decision = -(weights[0] + weights[1] * x_decision) / weights[2]
-
- plt.plot(x_decision, y_decision, color='green', label='Regression curve')
-
-
- plt.xlabel('X1')
- plt.ylabel('X2')
- plt.legend()
- plt.show()
散点图如下:
- # 预测
- x_test_with_intercept = np.c_[np.ones((x_test.shape[0], 1)), x_test]
- z_test = np.dot(x_test_with_intercept, weights)
- y_pred = np.round(sigmoid(z_test))
- # 逐个打印测试集的预测和真实标签
- print("逐个打印测试集的预测和真实标签:")
- for i in range(len(y_test)):
- print(f"样本 {i+1} - 真实标签: {y_test[i]}, 预测标签: {y_pred[i]}")
-
- # 计算准确率
- accuracy = np.mean(y_pred == y_test)
- print("测试集准确率:", accuracy)
输出结果如下:
- import numpy as np # 导入numpy库,用于数学运算
- import matplotlib.pyplot as plt # 导入matplotlib库,用于画图
- from sklearn.datasets import make_blobs # 从sklearn库中导入make_blobs函数,用于生成随机数据
-
- # 定义sigmoid函数
- def sigmoid(z): # 定义一个叫sigmoid的函数,输入参数是z
- return 1 / (1 + np.exp(-z)) # 返回1除以(1加上e的-z次方)
-
- # 定义梯度上升算法
- def tdss(x, y, alpha=0.01, num_iterations=1000): # 定义一个叫tdss的函数,输入参数是x, y, alpha, num_iterations
- m, n = x.shape # 获取x的形状,赋值给m和n
- weights = np.zeros(n) # 创建一个全为0的长度为n的数组,赋值给weights
-
- for _ in range(num_iterations): # 循环num_iterations次
- z = np.dot(x, weights) # 计算x和weights的点积,赋值给z
- h = sigmoid(z) # 使用定义好的sigmoid函数计算z的sigmoid值,赋值给h
- error = y - h # 计算y和h的差,赋值给error
- gradient = np.dot(x.T, error) / m # 计算x的转置和error的点积再除以m,赋值给gradient
- weights += alpha * gradient # 更新weights
-
- return weights # 返回weights
-
- if __name__=='__main__':
- # 输出训练集和测试集
- # 使用make blobs函数,在平面上生成60个随机样本包含两个类别
- x, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.5) # 生成包含60个随机样本的数据,赋值给x, y
- x_with_intercept = np.c_[np.ones((x.shape[0], 1)), x] # 在x前加一列全为1的数据,赋值给x_with_intercept
-
- # 分离出训练集和测试集
- x_train, y_train = x[:50], y[:50] # 获取x和y的前50个数据,赋值给x_train, y_train
- x_test, y_test = x[50:], y[50:] # 获取x和y的后10个数据,赋值给x_test, y_test
- print("训练集样本:")
- for i in range(len(x_train)): # 遍历训练集的每一个数据
- print(f"样本 {i+1} - 特征: {x_train[i]}, 标签: {y_train[i]}") # 打印训练集每个样本的特征和标签
-
- print("\n测试集样本:")
- for i in range(len(x_test)): # 遍历测试集的每一个数据
- print(f"样本 {i+1} - 特征: {x_test[i]}, 真实标签: {y_test[i]}") # 打印测试集每个样本的特征和真实标签
- # 训练模型
- weights = tdss(x_with_intercept, y) # 调用定义好的tdss函数进行模型训练,返回的结果赋值给weights
- # 预测
- x_test_with_intercept = np.c_[np.ones((x_test.shape[0], 1)), x_test] # 在测试集x_test前加一列全为1的数据,赋值给x_test_with_intercept
- z_test = np.dot(x_test_with_intercept, weights) # 计算x_test_with_intercept和weights的点积,赋值给z_test
- y_pred = np.round(sigmoid(z_test)) # 使用sigmoid函数计算z_test的sigmoid值并四舍五入,赋值给y_pred
- # 逐个打印测试集的预测和真实标签
- print("逐个打印测试集的预测和真实标签:")
- for i in range(len(y_test)): # 遍历测试集的每一个数据
- print(f"样本 {i+1} - 真实标签: {y_test[i]}, 预测标签: {y_pred[i]}") # 打印每个样本的真实标签和预测标签
-
- # 计算准确率
- accuracy = np.mean(y_pred == y_test) # 计算预测准确率,赋值给accuracy
- print("测试集准确率:", accuracy) # 打印测试集准确率
- # 绘制散点图和决策边界
- plt.scatter(x[y == 1, 0], x[y == 1, 1], color='blue', marker='o', label='label1') # 画散点图,蓝色代表标签1
- plt.scatter(x[y == 0, 0], x[y == 0, 1], color='red', marker='s', label='label0') # 画散点图,红色代表标签0
-
- x_decision = np.array([np.min(x[:, 0]), np.max(x[:, 0])]) # 创建一个包含x第一列最小值和最大值的数组,赋值给x_decision
- y_decision = -(weights[0] + weights[1] * x_decision) / weights[2] # 根据权重计算决策边界的y值,赋值给y_decision
-
- plt.plot(x_decision, y_decision, color='green', label='Regression curve') # 画决策边界
-
- plt.xlabel('X1') # 设置x轴标签
- plt.ylabel('X2') # 设置y轴标签
- plt.legend() # 显示图例
- plt.show() # 展示图形
并没有什么特别需要注意的问题,所以我找了一些可以提升准确率和性能的方法:
1.特征选择:选择与预测目标密切相关的特征,可以增强模型的预测能力。可以考虑使用相关性分析、卡方检验、互信息法等特征选择方法,以选择与目标变量相关性较强的特征。
2.数据预处理:对数据进行预处理可以改善模型的性能。数据预处理包括缺失值处理、异常值处理、数据标准化等。可以使用插值、平均值填充、回归等方法处理缺失值;使用箱线图、3σ原则等方法处理异常值;使用Z-score等方法进行数据标准化。
3.模型参数调整:可以通过调整模型参数来提高模型性能。例如,通过调整学习率(或步长)、迭代次数、正则化参数等参数,可以优化模型的收敛速度和预测精度。
优点:
缺点:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。