传统编程要求开发者明晰规定计算机执行任务的逻辑和条条框框的规则。然而,在机器学习的魔法领域,我们向计算机系统灌输了海量数据,让它在数据的奔流中领悟模式与法则,自主演绎未来,不再需要手把手的指点迷津。 机器学习,犹如三千世界的奇幻之旅,分为监督学习、无监督学习和强化学习等多种类型,各具神奇魅力。监督学习如大师传道授业,算法接收标签的训练数据,探索输入与输出的神秘奥秘,以精准预测未知之境。无监督学习则是数据丛林的探险者,勇闯没有标签的领域,寻找隐藏在数据深处的秘密花园。强化学习则是一场与环境的心灵对话,智能体通过交互掌握决策之术,追求最大化的累积奖赏。 机器学习,如涓涓细流,渗透各行各业。在图像和语音识别、自然语言处理、医疗诊断、金融预测等领域,它在智慧的浪潮中焕发生机,将未来的可能性绘制得更加丰富多彩。
逻辑回归是一种用于解决二分类问题的统计学习方法。尽管其名字中包含"回归"一词,但实际上,逻辑回归是一种分类算法,用于预测一个样本属于两个类别中的哪一个。 逻辑回归的核心思想是通过一个称为"逻辑函数"或"sigmoid函数"的特殊函数,将线性组合的输入特征映射到0和1之间的概率值。该函数的输出可以被解释为属于正类别的概率。在二分类问题中,逻辑回归通过设置一个阈值(通常为0.5),将概率大于阈值的样本预测为正类别,而概率小于阈值的样本预测为负类别。 逻辑回归模型的训练过程涉及到找到最适合拟合训练数据的参数,通常使用最大似然估计等方法来实现。由于其简单、高效且易于解释的特点,逻辑回归在实际应用中广泛用于医学、社会科学、经济学等领域的二分类问题。
资源获取:关注公众号【科创视野】回复:机器学习实验
(1)加深对有监督学习的理解和认识; (2)了解逻辑回归的损失函数; (3)掌握逻辑回归的优化方法; (4)了解sigmoid函数; (5)了解逻辑回归的应用场景; (6)应用LogisticRegression实现逻辑回归预测; (7)理解精确率、召回率指标的区别。
(1)安装机器学习必要库,如NumPy、Pandas、Scikit-learn等;
(2)配置环境用来运行 Python、Jupyter Notebook和相关库等内容。
假设你是某大学招生主管,你想根据两次考试的结果决定每个申请者的录取机会。现有以往申请者的历史数据,可以此作为训练集建立逻辑回归模型,并用其预测某学生能否被大学录取。请按要求完成实验。建议使用 python 编程实现。
数据集:
文件 ex2data1.txt 为该实验的数据集,第一列、第二列分别表示申请者两次考试的成绩,第三列表示录取结果(1 表示录取,0 表示不录取)。2.4 实验内容
总体步骤:
1.请导入数据并进行数据可视化,观察数据分布特征。(建议用 python 的matplotlib)
2.将逻辑回归参数初始化为 0,然后计算代价函数(cost function)并求出初始值。
3.选择一种优化方法求解逻辑回归参数。
4.某学生两次考试成绩分别为 42、85,预测其被录取的概率。
5.画出分类边界。
具体内容:
1.导入数据并进行数据可视化,观察数据分布特征。(建议用 python 的matplotlib)
图1
运行结果:
图2
代码:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import ticker
def plot_data():
# 首先需要读取数据
raw_data = pd.read_csv("data/data.csv")
# 从名为 "data.csv" 的文件中读取原始数据
raw_data.columns = ['first', 'second', 'admited']
# 为数据的列添加标签,分别为 'first', 'second', 'admited'
# 接下来将数据中的 0 和 1 分开存储
admit_array_x = []
# 存储通过测试的数据的第一次考试成绩
admit_array_y = []
# 存储通过测试的数据的第二次考试成绩
not_admit_array_x = []
# 存储未通过测试的数据的第一次考试成绩
not_admit_array_y = []
# 存储未通过测试的数据的第二次考试成绩
for i in range(raw_data.shape[0]):
if raw_data.iloc[i][2] == 1:
admit_array_x.append(raw_data.iloc[i][0])
admit_array_y.append(raw_data.iloc[i][1])
else:
not_admit_array_x.append(raw_data.iloc[i][0])
not_admit_array_y.append(raw_data.iloc[i][1])
# 设置标题和横纵坐标的标注
plt.xlabel("Exam 1 score")
# 设置 x 轴标签为 "Exam 1 score"
plt.ylabel("Exam 2 score")
# 设置 y 轴标签为 "Exam 2 score"
# 设置通过测试和不通过测试数据的样式。
# marker: 记号形状, color: 颜色, s: 点的大小, label: 标注
plt.scatter(not_admit_array_x, not_admit_array_y, marker='o', color='red', s=15, label='Not admitted')
plt.scatter(admit_array_x, admit_array_y, marker='x', color='green', s=15, label='Admitted')
# 标注的显示位置:右上角
plt.legend(loc='upper right')
# 设置坐标轴上刻度的精度为一位小数。
# 因为训练数据中的分数的小数点太多,
# 若不限制坐标轴上刻度显示的精度,会影响最终散点图的美观度
plt.gca().xaxis.set_major_formatter(ticker.FormatStrFormatter('%.1f'))
plt.gca().yaxis.set_major_formatter(ticker.FormatStrFormatter('%.1f'))
# 显示图像
plt.show()
plot_data() #绘制图像
源码分析:
2.将逻辑回归参数初始化为 0,然后计算代价函数(cost function)并求出初始值。
图3
代码:
def init_data():
# 将数据初始化
data = pd.read_csv("data/data.csv")
# 从名为 "data.csv" 的文件中读取数据
data.columns = ['first', 'second', 'admited']
# 为数据的列添加标签,分别为 'first', 'second', 'admited'
# 尝试对数据进行标准化
column_list = list(data.columns)
# 获取数据集中的列名列表
min_value = []
# 存储每一列的最小值
max_value = []
# 存储每一列的最大值
for j in range(data.shape[1] - 1):
min_value.append(data[column_list[j]].min())
# 计算每一列的最小值并存储
max_value.append(data[column_list[j]].max())
# 计算每一列的最大值并存储
for i in range(data.shape[0]):
# 对每一个数据点进行标准化,将其转换为0到1之间的值
data.loc[i, column_list[j]] = (data.loc[i, column_list[j]] - min_value[j]) / (max_value[j] - min_value[j])
data_x = data.iloc[:, 0:2]
# 特征值,取第一列和第二列作为特征
data_y = data.iloc[:, -1]
# 标签,取最后一列作为标签
return data_x.values, data_y.values, min_value, max_value
3.选择一种优化方法求解逻辑回归参数。
图4
图5
运行结果:
图6
代码:
# 与逻辑回归有关的函数
# 定义 sigmoid 函数,用于将输入值映射到0到1之间
def sigmoid(z):
return 1 / (1 + np.exp(-z))
# 定义代价函数,用于计算逻辑回归模型的代价
def cost_function(X, y, theta):
m = len(y) # 样本数量
h = sigmoid(np.dot(X, theta)) # 计算假设函数的预测值
J = -(1/m) * np.sum(y * np.log(h) + (1-y) * np.log(1-h)) # 代价函数表达式
return J
# 定义梯度下降函数,用于更新模型参数
def gradient_descent(X, y, theta, alpha, num_iterations):
m = len(y) # 样本数量
J_history = [] # 存储每次迭代的代价值
for i in range(num_iterations):
h = sigmoid(np.dot(X, theta)) # 计算假设函数的预测值
gradient = np.dot(X.T, (h - y)) / m # 计算梯度
theta = theta - alpha * gradient # 更新模型参数
cost = cost_function(X, y, theta) # 计算当前模型参数下的代价
J_history.append(cost) # 将代价添加到代价历史列表中
return theta, J_history
# 逻辑回归主函数
# 从 CSV 文件读取数据
data = pd.read_csv('data/data.csv')
data.columns = ['first','second','admited']
# 提取特征和标签
data_x, data_y, min_value, max_value = init_data()
# 初始化参数
theta = np.zeros(2) # 将权重初始设置为0
alpha = 0.01 # 学习率
num_iterations = 1000 # 迭代次数
# 训练逻辑回归模型
theta, J_history = gradient_descent(data_x, data_y, theta, alpha, num_iterations)
# 绘制代价函数的变化曲线
plt.plot(J_history) # 绘制迭代次数与代价值之间的关系曲线
plt.xlabel('iteration') # 设置x轴标签
plt.ylabel('cost value') # 设置y轴标签
plt.title('curve of cost values') # 设置图的标题为"cost values的变化曲线"
# 显示图像
plt.show()
源码分析:
训练模型:
图7
运行结果:
图8
图9
代码:
########## 使用测试集进行测试 #####################
# 读取测试集数据
test_data = pd.read_csv('data/data_test.csv')
test_data.columns = ['first','second','admited']
# 测试集数据标准化
column_list = list(test_data.columns)
for j in range(test_data.shape[1]-1):
for i in range(test_data.shape[0]):
test_data.loc[i,column_list[j]] = (test_data.loc[i,column_list[j]]-min_value[j]) / (max_value[j]-min_value[j])
test_data_x = test_data.iloc[:,0:2].values
test_data_y = test_data.iloc[:,-1].values
# 输入 sigmoid 函数进行预测
prediction = sigmoid(np.dot(test_data_x, theta))
print(prediction)
# 输出正确率
num = 0 # 预测正确的个数
for i in range(len(prediction)):
if prediction[i] > 0.5:
temp_value = 1
else:
temp_value = 0
if test_data_y[i] == temp_value:
num = num + 1
print(f"模型的正确率为:{num/len(prediction)}")
################# 绘制决策边界 #################
# 定义决策边界的阈值
threshold = 0.5
# 生成网格点
x_min, x_max = data_x[:, 0].min() - 0.01, data_x[:, 0].max() + 0.01
y_min, y_max = data_x[:, 1].min() - 0.01, data_x[:, 1].max() + 0.01
h = 0.0001 # 网格点的间隔
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
# 对网格点进行预测
X_grid = np.c_[xx.ravel(), yy.ravel()]
Z = np.dot(X_grid, theta)
Z = sigmoid(Z)
Z = Z.reshape(xx.shape)
# 绘制决策边界和分类结果
plt.contourf(xx, yy, Z, alpha=0.8)
# 绘制决策边界
plt.scatter(data_x[:, 0], data_x[:, 1], c=data_y)
# 绘制样本点
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.title('Decision Boundary')
plt.show()
源码分析:
1.读取测试集数据:
2.测试集数据标准化:
3.使用sigmoid函数进行预测:
4.输出正确率:
5.绘制决策边界:
6.定义决策边界的阈值:
7.生成网格点:
8.对网格点进行预测:
9.绘制决策边界和分类结果:
4.某学生两次考试成绩分别为 42、85,预测其被录取的概率。
图10
代码:
# 当输入为42和85时,计算通过概率
# 标准化输入值
x1 = (42 - min_value[0]) / (max_value[0] - min_value[0])
x2 = (85 - min_value[1]) / (max_value[1] - min_value[1])
# 将输入值转换为数组
arr = np.array((x1, x2))
# 计算最终通过概率
print(f"通过概率为:{sigmoid(np.dot(arr, theta))}")
5.画出分类边界。
分类边界在第三步已经完成,如图9。
本次实验运用逻辑回归算法进行学生考试成绩和录取结果的分类预测,实现了数据可视化、参数初始化、代价函数计算、梯度下降优化、预测和决策边界绘制等关键步骤。
数据可视化阶段通过matplotlib库创建散点图,生动展示通过和不通过考试学生在两次考试成绩上的分布特征,直观呈现数据的分布情况。
参数初始化和代价函数计算中,将逻辑回归参数初始化为0,定义sigmoid函数和代价函数,用于映射输入值、度量预测与实际标签的差距,以及评估模型准确性。
在梯度下降优化中,通过迭代更新模型参数,减小代价函数的值,以找到最优模型参数。
预测阶段利用训练好的模型参数对测试集进行预测,计算模型的准确率,通过sigmoid函数输出的预测值表示学生被录取的概率。
决策边界绘制中,定义决策边界的阈值,生成网格点,通过对网格点预测和contourf函数绘制决策边界,直观观察模型的分类效果。使用scatter函数将训练集样本点绘制在图上,以不同颜色表示通过和不通过考试的学生,全面展示了模型的分类结果。
此实验深入理解了逻辑回归算法的原理和应用,并通过代码实现了相关功能。