人工智能 实验5 逻辑回归

【实验目的】掌握逻辑回归算法

【实验内容】处理样本,使用逻辑回归算法进行参数估计,并画出分类边界

【实验要求】写明实验步骤,必要时补充截图

1、参照"2.1梯度下降法实现线性逻辑回归.ipynb"和"2.2 sklearn实现线性逻辑回归.ipynb",在Jupyter Notebook中新建Python运行环境,以单元格为单位运行代码,在实验报告中解释每行代码的含义,分析运行结果,把运行结果截图保存到实验报告中,并比较两种实现方式的优劣。

2.1:

python 复制代码
import numpy as np  # 导入numpy库,用于数值计算
import matplotlib.pyplot as plt  # 导入matplotlib库,用于绘图

# 读取数据
data = np.genfromtxt("C:/Users/a1830/Desktop/实验5-逻辑回归/实验素材/LR-testSet.txt", delimiter=",")
data  # 打印读取的数据

# 特征:选择前两列
x_data = data[:,:-1]
# 标签:y
y_data = data[:,-1]

# 定义sigmoid函数  x=θ^T*X
def sigmoid_(x):
    return 1/(1+np.exp(-x))  # 返回sigmoid函数值

# 定义损失函数 xMat:x_data矩阵 yMat:y_data矩阵 ws:参数向量的转置
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):
    # 将ndarry类型转为矩阵
    xMat = np.mat(xArr)
    yMat = np.mat(yArr)
    
    # 初始化学习率
    lr = 0.001
    
    # 初始化迭代次数
    epochs = 10000
    
    # 取出 样本个数m 以及 特征个数n
    m,n = np.shape(xMat)  
    
    # 初始化的θ --> θ^T*xMat   θ0*x0+θ1*x1+θ2*x2  
    ws = np.mat(np.ones((n,1)))
    
    # 初始化损失列表
    costList = [] 
    
    # 迭代
    for i in range(epochs+1):
        # 求导
        # 1.h(x)  100*3 3*1 --> 100*1 -->每个样本都有一个h(x)
        h = sigmoid_(xMat*ws)
        # print(f"xMat shape:{np.shape(xMat)}")
        # print(f"ws shape:{np.shape(ws)}")

        # 矩阵乘法:n*m m*1 --> n*1 -->
        # xMat:m*n  3*100   m*1 1*100
        # h-->预测值  (m*1)
        # yMat-->真实值 (m*1)
        ws_grad = xMat.T*(h - yMat.T)/m
        # print(f"xmat.T shape{np.shape(xMat.T)}")
        # print(f"yMat shape{np.shape(h - yMat.T)}")

        # print(np.shape(ws_grad))
        
        # 更新ws-->theta向量
        ws = ws - lr*ws_grad
        
        if i%50 == 0:
            costList.append(cost_(xMat,yMat,ws))  # 每50次迭代记录一次损失值
            
    # 返回theta向量ws,以及损失列表
    return ws,costList

# 训练模型
ws,costList = gradAscent(x_data,y_data)
print(ws)  # 打印训练得到的权重向量

"""
可视化
- 横轴:x1
- 纵轴:x2
x1*theta1+x2*theta2+theta0=0
x2 = -(x1*theta1+theta0)/theta2
"""
"""
可视化
- y_data为0是一个类别,圆
- y_data为1是一个类型,叉
实现:构建x1,x2
"""
def plot_logi():
    # 初始化列表
    x_0 = []
    y_0 = []
    x_1 = []
    y_1 = []
    # 切分不同类别的数据
    for i in range(len(x_data)):
        # 取类别为0的数据
        if y_data[i] == 0:
            # 将特征1添加到x_0中
            x_0.append(x_data[i,0])
            # 将特征2添加到y_0中
            y_0.append(x_data[i,1])
        else:
            # 将特征1添加到x_1中
            x_1.append(x_data[i,0])
            # 将特征2添加到y_1中
            y_1.append(x_data[i,1])

    # 画图
    plt.scatter(x_0,y_0,c="skyblue",marker="o",label="class0")
    plt.scatter(x_1,y_1,c="red",marker="x",label="class1")    
    plt.legend()


# 绘制点
plot_logi()

# 初始化测试集的数据
x_test = [[-4],[3]]
# 计算分类函数
y_test = -(x_test*ws[1]+ws[0])/ws[2]
# 可视化
plt.plot(x_test,y_test)
plt.show()

# 绘制loss曲线
# 生成0,10000
x = np.linspace(0,10000,201)
plt.plot(x,costList)
plt.xlabel("epochs")
plt.ylabel("Cost")
plt.show()


    
    
    
plot_logi()
plt.show()
# 特征:选择前两列
x_data = data[:,:-1]
# 标签:y
y_data = data[:,-1]

# θ^T*X  给X添加一列全为1的数据
X_data = np.concatenate((np.ones((len(x_data),1)),x_data),axis=1)

# 定义sigmoid函数,输入为x=θ^T*X
def sigmoid_(x):
    return 1/(1+np.exp(-x))

# 定义损失函数,输入为xMat:x_data矩阵, yMat:y_data矩阵, ws:参数向量的转置
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):
    # 将ndarry类型转为矩阵
    xMat = np.mat(xArr)
    yMat = np.mat(yArr)
    
    # 初始化学习率
    lr = 0.001
    
    # 初始化迭代次数
    epochs = 10000
    
    # 取出样本个数m以及特征个数n
    m,n = np.shape(xMat)  
    
    # 初始化的θ --> θ^T*xMat   θ0*x0+θ1*x1+θ2*x2  
    ws = np.mat(np.ones((n,1)))
    
    # 初始化损失列表
    costList = [] 
    
    # 迭代
    for i in range(epochs+1):
        # 求导
        # 1.h(x)  100*3 3*1 --> 100*1 -->每个样本都有一个h(x)
        h = sigmoid_(xMat*ws)
        
        # 矩阵乘法:n*m m*1 --> n*1 -->
        # xMat:m*n  3*100   m*1 1*100
        # h-->预测值  (m*1)
        # yMat-->真实值 (m*1)
        ws_grad = xMat.T*(h - yMat.T)/m
        
        # 更新ws-->theta向量
        ws = ws - lr*ws_grad
        
        if i%50 == 0:
            costList.append(cost_(xMat,yMat,ws))
            
    # 返回theta向量ws,以及损失列表
    return ws,costList

# 训练模型
ws,costList = gradAscent(X_data, y_data)
print(ws)

"""
可视化部分
- 横轴:x1
- 纵轴:x2
x1*theta1+x2*theta2+theta0=0
x2 = -(x1*theta1+theta0)/theta2
"""
# 绘制点
plot_logi()

# 初始化测试集的数据
x_test = [[-4],[3]]
# 计算分类函数
y_test = -(x_test*ws[1]+ws[0])/ws[2]
# 可视化
plt.plot(x_test,y_test)
plt.show()

# 绘制loss曲线
# 生成0,10000
x = np.linspace(0,10000,201)
plt.plot(x,costList)
plt.xlabel("epochs")
plt.ylabel("Cost")
plt.show()

运行结果

2.2:

python 复制代码
import numpy as np  # 导入numpy库,用于数值计算
import matplotlib.pyplot as plt  # 导入matplotlib库中的pyplot模块,用于绘图

# 读取数据
data = np.genfromtxt("C:/Users/a1830/Desktop/人工智能 实验5-逻辑回归/实验素材/LR-testSet.txt", delimiter=",")  # 从指定路径读取数据文件,使用逗号作为分隔符
data  # 打印读取的数据

# 特征:选择前两列
x_data = data[:,:-1]  # 提取数据的前两列作为特征
# 标签:y
y_data = data[:,-1]  # 提取数据的最后一列作为标签

def plot_logi():
    # 初始化列表
    x_0 = []  # 存储类别为0的特征1
    y_0 = []  # 存储类别为0的特征2
    x_1 = []  # 存储类别为1的特征1
    y_1 = []  # 存储类别为1的特征2
    # 切分不同类别的数据
    for i in range(len(x_data)):  # 遍历所有数据点
        # 取类别为0的数据
        if y_data[i] == 0:  # 如果当前数据点的标签为0
            # 将特征1添加到x_0中
            x_0.append(x_data[i,0])  # 添加特征1到x_0列表
            # 将特征2添加到y_0中
            y_0.append(x_data[i,1])  # 添加特征2到y_0列表
        else:  # 如果当前数据点的标签不为0(即为1)
            # 将特征1添加到x_1中
            x_1.append(x_data[i,0])  # 添加特征1到x_1列表
            # 将特征2添加到y_1中
            y_1.append(x_data[i,1])  # 添加特征2到y_1列表
    
    # 画图
    plt.scatter(x_0,y_0,c="skyblue",marker="o",label="class0")  # 绘制类别为0的散点图,颜色为天蓝色,标记为圆圈
    plt.scatter(x_1,y_1,c="red",marker="x",label="class1")  # 绘制类别为1的散点图,颜色为红色,标记为叉号
    plt.legend()  # 显示图例
    
plot_logi()  # 调用函数绘制初始散点图

# 训练模型
from sklearn.linear_model import LogisticRegression  # 导入LogisticRegression类
logistic = LogisticRegression()  # 创建LogisticRegression对象
logistic.fit(x_data,y_data)  # 使用数据拟合模型

# 截距
print(logistic.intercept_)  # 打印模型的截距项
# theta1 theta2
print(logistic.coef_)  # 打印模型的系数(权重)
# x2 = -(x1*theta1+theta0)/theta2

# 画出散点
plot_logi()  # 再次调用函数绘制散点图

# 画出决策边界
x_test = np.array([[-4],[3]])  # 定义测试数据,用于绘制决策边界
y_test = -(x_test*logistic.coef_[0,0]+logistic.intercept_)/logistic.coef_[0,1]  # 根据模型参数计算决策边界的y值
plt.plot(x_test,y_test)  # 绘制决策边界
plt.show()  # 显示图形

print(logistic.score(x_data,y_data))  # 打印模型在训练数据上的准确率

运行结果

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

优势:

  1. 完全控制:你可以完全控制优化过程,包括学习率、批量大小、正则化方法等。
  2. 灵活性:可以自定义损失函数和正则化项,适用于各种复杂的模型。
  3. 适用性广:不仅限于逻辑回归,还可以应用于其他类型的机器学习模型。
  4. 性能优化:可以根据具体需求进行优化,例如使用动量法、AdaGrad、RMSProp等高级优化算法。
  5. 并行计算:可以更容易地实现多线程或GPU加速,提高训练速度。

劣势:

  1. 实现复杂:需要编写更多的代码来实现梯度下降法,包括前向传播、损失计算、梯度计算和参数更新。
  2. 调试困难:由于涉及多个步骤和超参数,调试和优化可能更加困难。
  3. 易出错:手动实现容易引入错误,特别是在处理大规模数据时。
  4. 开发时间:相比sklearn,手动实现可能需要更多的开发时间。

sklearn实现线性逻辑回归

  1. 优势:
  1. 易用性:提供简洁的API,易于使用和集成。
  2. 功能丰富:除了基本的逻辑回归,还支持多种正则化方法、多分类问题等。
  3. 性能优化:sklearn中的实现经过了优化,通常比手动实现更高效。
  4. 社区支持:有大量的文档和社区资源,便于解决问题和学习。
  5. 扩展性:可以与其他机器学习算法或深度学习框架结合使用。
  1. 劣势:
  1. 灵活性不足:只支持标准的交叉熵损失和L2正则化(岭回归),无法自定义损失函数或正则化方法。
  2. 优化算法的选择有限:默认使用liblinear或lbfgs等优化算法,这些算法可能不适合所有问题。
  3. 内存消耗:在处理非常大的数据集时,可能会遇到内存限制。
  4. 并行计算:不支持多线程或GPU加速,这在处理大型数据集时可能会成为瓶颈。
  5. 解释性差:提供的模型接口相对简单,缺乏对模型内部机制的深入解释和可视化工具。

梯度下降法实现线性逻辑回归适合需要高度定制化和控制的场景,但实现复杂且调试困难。

sklearn实现线性逻辑回归适合快速原型设计和生产环境,易于使用和集成,但在灵活性和控制力方面有所欠缺。

2、读取ex2data1.txt中的数据,建立样本集,使用逻辑回归算法得到参数估计值。并在坐标图中画出分界图。

提示:参考"成绩分类版本1.ipynb"

估计值为0.89

结合自己的知识背景及兴趣,选做以下题目:

3、读取"简单分类数据.txt"中的数据,建立样本集,使用逻辑回归算法得到参数值,并在坐标图中画出分界线

4、逻辑回归算法可以看成是只有一个神经元的神经网络,打开"链式逻辑回归.ipynb"文档,参考第四章简单逻辑回归ppt32-34页将其填充完整。读取"链式逻辑回归.txt"中的数据,建立样本集,使用神经网络式逻辑回归算法得到参数估计值。并在坐标图中画出分界图

5、打开"链式逻辑回归分类猫.ipynb"文档,参考第一题中的算法生成可以分类图片的模型,用测试集获得正确率,然后用任意图片测试模型是否能正确判断是否有猫

判断结果:

相关推荐
AL.千灯学长6 分钟前
DeepSeek接入Siri(已升级支持苹果手表)完整版硅基流动DeepSeek-R1部署
人工智能·gpt·ios·ai·苹果vision pro
MZWeiei8 分钟前
PTA:运用顺序表实现多项式相加
算法
GISer_Jing15 分钟前
Javascript排序算法(冒泡排序、快速排序、选择排序、堆排序、插入排序、希尔排序)详解
javascript·算法·排序算法
cookies_s_s16 分钟前
Linux--进程(进程虚拟地址空间、页表、进程控制、实现简易shell)
linux·运维·服务器·数据结构·c++·算法·哈希算法
LCG元37 分钟前
大模型驱动的围术期质控系统全面解析与应用探索
人工智能
lihuayong1 小时前
计算机视觉:主流数据集整理
人工智能·计算机视觉·mnist数据集·coco数据集·图像数据集·cifar-10数据集·imagenet数据集
不想编程小谭1 小时前
力扣LeetCode: 2506 统计相似字符串对的数目
c++·算法·leetcode
政安晨1 小时前
政安晨【零基础玩转各类开源AI项目】DeepSeek 多模态大模型Janus-Pro-7B,本地部署!支持图像识别和图像生成
人工智能·大模型·多模态·deepseek·janus-pro-7b
一ge科研小菜鸡1 小时前
DeepSeek 与后端开发:AI 赋能云端架构与智能化服务
人工智能·云原生
冰 河1 小时前
‌最新版DeepSeek保姆级安装教程:本地部署+避坑指南
人工智能·程序员·openai·deepseek·冰河大模型