logistic回归模型的实现

一、什么是logistic回归

Logistic回归是一种分类模型,常用来解决二分类问题(比如预测一个邮件是“垃圾邮件”还是“正常邮件”)。虽然名字里有“回归”,但它其实是用来做分类的

它的目标是根据输入的特征,也就是预测事件发生的概率

二、为什么用Logistic回归?

线性回归预测的是一个连续值,但分类问题要输出类别(0或1)

Logistic回归通过一个“sigmoid函数”把线性组合的结果映射到0到1之间,表示概率

三、数学表达

假设输入特征是一个向量 x=(x1,x2,...,xn),模型有参数 w=(w1,w2,...,wn)和偏置项 b

1. 线性组合

先对输入做线性组合:

2. sigmoid函数

接着用sigmoid函数把 z 转换成概率:

3. 最终概率表达

所以,预测正类概率是:

相应的,预测负类的概率是:

四、决策边界

模型输出概率后,通常会设一个阈值(默认是0.5),

如果 P(y=1∣x)>0.5,就预测为类别1

否则预测为类别0

这个阈值也可以根据实际需求调整

 五、训练模型

训练时,目标是找到参数 w 和 b,使得预测概率最大程度符合训练数据

用最大似然估计(MLE)的方法:

对于给定参数 θ,似然函数定义为数据在该参数下的联合概率:

通常假设数据样本相互独立同分布,则联合概率是单个概率的乘积: 

损失函数用交叉熵损失(log loss): 

 

通过梯度下降等优化方法来最小化损失函数,找到最优参数

六、Logistic回归的优点和局限

优点:

1.计算简单,训练快

2.输出概率,解释性强

3.对线性可分问题效果好

4.可以用正则化(L1、L2)防止过拟合

局限:

1.只能处理线性边界(特征和结果之间线性关系)

2.对非线性关系表现不好,需做特征工程或用非线性模型

3.容易受异常值影响

七、Logistic回归模型的代码实现

代码实现:

import numpy as np
import matplotlib.pyplot as plt

def load_data(filename):
    # 载入数据,前两列为特征,第三列为标签
    data = np.loadtxt(filename)
    X = data[:, 0:2]  # 前两列特征
    y = data[:, 2]    # 第三列标签
    return X, y

def sigmoid(z):
    # sigmoid 函数
    return 1.0 / (1.0 + np.exp(-z))

def add_intercept(X):
    # 添加截距项(偏置),使矩阵第一列全为1
    if X.ndim == 1:
        return np.concatenate(([1], X))
    else:
        intercept = np.ones((X.shape[0], 1))
        return np.concatenate((intercept, X), axis=1)

def gradient_descent(X, y, theta, alpha, num_iters):
    # 梯度下降优化theta参数
    m = len(y)
    J_history = []
    
    for i in range(num_iters):
        h = sigmoid(X.dot(theta))        # 预测概率
        error = h - y                   # 误差
        gradient = X.T.dot(error) / m   # 梯度
        theta -= alpha * gradient       # 更新参数
        
        if i % 100 == 0:
            # 计算交叉熵损失
            cost = (-y * np.log(np.clip(h, 1e-5, 1-1e-5)) - 
                   (1 - y) * np.log(np.clip(1 - h, 1e-5, 1-1e-5))).mean()
            J_history.append(cost)
            print(f'Iteration {i}, Cost: {cost}')
    
    return theta, J_history

def predict(X, theta):
    # 根据模型参数预测类别和概率
    prob = sigmoid(np.dot(X, theta))
    prediction = (prob >= 0.5).astype(int)
    # 确保单个样本预测返回标量而非数组
    if isinstance(prob, np.ndarray) and prob.size == 1:
        return prediction.item(), prob.item()
    return prediction, prob

def plot_decision_boundary(X, y, theta, user_input=None, user_prediction=None):
    # 画出数据点和决策边界
    plt.figure(figsize=(10, 6))
    
    # 原始数据点绘制,不同类别用不同颜色和形状
    plt.scatter(X[y==0, 0], X[y==0, 1], c='blue', marker='o', label='Class 0')
    plt.scatter(X[y==1, 0], X[y==1, 1], c='red', marker='x', label='Class 1')
    
    # 用户输入点绘制,颜色和形状根据预测类别不同而变化
    if user_input is not None and user_prediction is not None:
        marker_color = 'green' if user_prediction == 0 else 'purple'
        marker_style = 'o' if user_prediction == 0 else 'x'
        plt.scatter([user_input[0]], [user_input[1]], 
                   c=marker_color, marker=marker_style, s=100, edgecolors='black', 
                   label=f'User Input (Prediction: {user_prediction})')
    
    # 决策边界绘制:根据theta参数算出对应的x2
    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    plot_x = np.array([x_min, x_max])
    plot_y = (-1 / theta[2]) * (theta[1] * plot_x + theta[0])
    
    plt.plot(plot_x, plot_y, 'g-', label='Decision Boundary')
    plt.xlabel('Feature 1')
    plt.ylabel('Feature 2')
    plt.legend()
    
    # 显示决策边界的解析式
    equation = f'x2 = {-theta[0]/theta[2]:.4f} + {-theta[1]/theta[2]:.4f} * x1'
    plt.annotate(equation, xy=(0.05, 0.95), xycoords='axes fraction')
    
    plt.title('Logistic Regression Classification Result')
    plt.show()

def get_user_input():
    # 获取用户输入的两个特征值,支持空格或逗号分隔
    try:
        user_input = input("Enter two feature values (separated by space or comma, e.g. '1.5 3.2' or 'q' to quit): ")
        
        if user_input.lower() == 'q':
            return None
            
        if ',' in user_input:
            values = user_input.split(',')
            x1 = float(values[0].strip())
            x2 = float(values[1].strip())
        else:
            values = user_input.split()
            x1 = float(values[0])
            x2 = float(values[1])
            
        return np.array([x1, x2])
    except:
        print("Invalid input, please enter two numbers or 'q' to quit")
        return get_user_input()

def main():
    # 训练模型
    print("Loading data and training logistic regression model...")
    X, y = load_data(r'C:\Users\26687\Desktop\test\deep learning\e5\testSet (1).txt')
    X_with_intercept = add_intercept(X)
    
    initial_theta = np.zeros(X_with_intercept.shape[1])
    alpha = 0.01
    num_iters = 1000
    
    theta, _ = gradient_descent(X_with_intercept, y, initial_theta, alpha, num_iters)
    
    # 计算准确率
    predictions, _ = predict(X_with_intercept, theta)
    accuracy = (predictions == y).mean() * 100
    print(f"Model accuracy: {accuracy:.2f}%")
    print(f"Decision boundary equation: x2 = {-theta[0]/theta[2]:.4f} + {-theta[1]/theta[2]:.4f} * x1")
    
    # 用户输入预测
    print("\n===== Prediction Mode =====")
    print("Now you can enter feature values for prediction")
    
    while True:
        user_features = get_user_input()
        
        if user_features is None:
            print("Exiting program.")
            break
            
        # 添加截距项并预测
        user_features_with_intercept = add_intercept(user_features)
        user_prediction, probability = predict(user_features_with_intercept, theta)
        
        # 输出预测结果
        print(f"\nInput features: X1={user_features[0]}, X2={user_features[1]}")
        print(f"Prediction result: Class {user_prediction}")
        print(f"Prediction probability: {probability:.4f}")
        
        # 可视化结果
        plot_decision_boundary(X, y, theta, user_features, user_prediction)

if __name__ == '__main__':
    main()

训练结果:

 

可视化展示:

上图为根据数据集训练得到的logistic回归模型的分类图 ,X为用户输入的分类结果

 说明:用户可自定义输入两个数,模型进行预测,输出为0或1 

 

 

 声明:本博客仅为个人理解,如有错误,敬请谅解并指出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值