逻辑回归是一种“监督式机器学习”算法,用于模拟某个类别或事件的概率。当数据线性可分且结果为二元或二分性质时,通常使用逻辑回归。这意味着逻辑回归通常用于二元分类问题。二元分类指的是预测输出变量为两个离散类别的情况,例如是/否、通过/失败、赢/输、癌症/非癌症等。
简单逻辑回归:使用单个独立变量来预测输出。多重逻辑回归:使用多个独立变量来预测输出。
尽管逻辑回归通常用于二元分类,但它可以扩展到解决多类分类问题。多项式逻辑回归:输出变量为三个或更多无自然排序的离散类别,例如食物质地:脆、软、脆,或头发颜色:金发、棕色、深褐色、红色。有序逻辑回归:输出变量为三个或更多有序级别的离散类别,例如客户评级:极度不喜欢、不喜欢、中立、喜欢、极度喜欢,或收入水平:低收入、中等收入、高收入。
在深入逻辑回归之前,建议阅读有关简单线性回归的文章,以便复习。现在,尝试使用线性回归来解决二元分类问题。假设有一个数据集,它是线性可分的,并且输出为两个离散类别(0,1)。在线性回归中,绘制一条直线(最佳拟合线)L1,使得所有数据点到该线的距离之和最小。直线L1的方程是y=mx+c,其中m是斜率,c是y截距。
        # 线性回归模型示例
        y = mx + c
    
定义一个阈值T=0.5,超过该阈值的输出属于类别1,否则属于类别0。然而,线性回归模型在预测值可能超出(0,1)范围以及数据中存在异常值时会增加错误率的情况下存在问题。因此,逻辑回归在这里是必要的。
逻辑回归方程与线性回归模型非常相似。假设有一个模型,其中有一个预测变量“x”和一个伯努利响应变量“ŷ”,p是ŷ=1的概率。线性方程可以写成:
        p = b0 + b1 * x
    
方程右侧(b0 + b1 * x)是一个线性方程,可能包含超出范围(0,1)的值。但知道概率总是在(0,1)范围内。为了解决这个问题,预测赔率而不是概率。赔率是事件发生概率与不发生概率的比率。赔率 = p / (1-p)。方程1可以重写为:
        p / (1 - p) = b0 + b1 * x
    
为了处理负数,预测赔率的对数。对数赔率 = ln(p / (1-p))。方程2可以重写为:
        ln(p / (1 - p)) = b0 + b1 * x
    
为了从方程3中恢复p,在两边应用指数。exp(ln(p / (1-p))) = exp(b0 + b1 * x)。根据对数的反规则,p / (1 - p) = e^(b0 + b1 * x)。通过简单的代数操作,得到:
        p = e^(b0 + b1 * x) / (1 + e^(b0 + b1 * x))
    
类似地,具有‘n’个预测变量的逻辑模型的方程如下:
        p = 1 / (1 + e^-(b0 + b1 * x1 + b2 * x2 + ... + bn * xn))
    
右侧的部分看起来熟悉吗?是的,它是sigmoid函数。它有助于将输出压缩在0和1之间。sigmoid函数:sigmoid函数有助于将任何预测值的概率映射到0和1之间的另一个值。从线性方程开始,最终得到了逻辑回归模型,这得益于sigmoid函数。
        # 定义数据集URL
        dataset_url = "https://raw.githubusercontent.com/harika-bonthu/02-linear-regression-fish/master/datasets_229906_491820_Fish.csv"
        # 从鱼类数据集创建pandas数据框
        import pandas as pd
        fish = pd.read_csv(dataset_url, error_bad_lines=False)
        fish.head()
        # 检查目标特征的唯一类别。数据集包含关于7种鱼类的信息
        fish['Species'].unique()
        # 检查是否有任何空值。数据集没有空值。
        fish.isnull().sum()
        # 定义输入和目标变量
        X = fish.iloc[:, 1:]
        y = fish.loc[:, 'Species']
        # 使用MinMaxScaler缩放输入特征
        from sklearn.preprocessing import MinMaxScaler
        scaler = MinMaxScaler()
        scaler.fit(X)
        X_scaled = scaler.transform(X)
        # 使用LabelEncoder对目标变量进行标签编码
        from sklearn.preprocessing import LabelEncoder
        label_encoder = LabelEncoder()
        y = label_encoder.fit_transform(y)
        # 使用train_test_split将数据集分割为训练集和测试集
        from sklearn.model_selection import train_test_split
        X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
        # 构建和训练模型
        from sklearn.linear_model import LogisticRegression
        clf = LogisticRegression()
        # 训练模型
        clf.fit(X_train, y_train)
        # 预测输出
        y_pred = clf.predict(X_test)
        # 计算准确率
        from sklearn.metrics import accuracy_score
        accuracy = accuracy_score(y_test, y_pred)
        print("Accuracy: {:.2f}%".format(accuracy * 100))
    
        from sklearn.metrics import confusion_matrix
        cf = confusion_matrix(y_test, y_pred)
        import matplotlib.pyplot as plt
        import seaborn as sns
        plt.figure()
        sns.heatmap(cf, annot=True)
        plt.xlabel('Prediction')
        plt.ylabel('Target')
        plt.title('Confusion Matrix')