逻辑回归案例
逻辑回归
逻辑回归是一种用于分类的机器学习算法,尽管名字中有“回归”,但它主要用于二分类问题。
它的核心思想是:通过一个逻辑函数(通常是 Sigmoid 函数)将线性回归的结果映射到 0 到 1 之间,这样输出就可以表示为某个类别的概率。
简单来说,逻辑回归的流程是:
- 用一些特征来描述数据(比如一个人的年龄、收入等)。
- 定义一个线性方程,将这些特征组合起来。
- 把线性方程的结果通过 Sigmoid 函数转换成概率值(0 到 1 之间)。
- 根据概率值来判断数据属于哪个类别(比如概率大于 0.5 划为类别 1,否则划为类别 0)。
案例:判断一个游戏账号是否存在安全风险
假设我们有一个游戏平台,想判断一个账号是否存在被盗用或存在安全风险的情况。我们可以用账号的以下特征来判断:
- 账号最近一次登录距离上次登录的时间间隔(秒)
- 账号最近一次登录的地点变更次数
- 账号是否开启了双重认证(1 表示开启,0 表示未开启)
我们可以将账号分为两类:
- 类别 1:存在安全风险
- 类别 0:不存在安全风险
# 导入必要的库
import numpy as np # 用于数组和数学运算
import matplotlib.pyplot as plt # 用于数据可视化# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置字体为黑体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题# 定义数据集
# 每一行表示一个游戏账号的特征和标签(是否存在安全风险)
# 第一列:最近一次登录距离上次登录的时间间隔(秒)
# 第二列:最近一次登录的地点变更次数
# 第三列:是否开启了双重认证(1 表示开启,0 表示未开启)
# 第四列:标签(1 表示存在安全风险,0 表示不存在安全风险)
data = np.array([[3600, 2, 0, 1], # 存在安全风险的账号[7200, 3, 0, 1],[1800, 1, 1, 0], # 不存在安全风险的账号[900, 0, 1, 0],[10800, 4, 0, 1],[1200, 1, 1, 0],[2400, 2, 0, 1],[600, 0, 1, 0]
])# 提取特征(前三列)和标签(最后一列)
X = data[:, :3] # 提取特征数据
y = data[:, 3] # 提取标签数据# 数据标准化(特征缩放)
from sklearn.preprocessing import StandardScaler # 导入标准化工具scaler = StandardScaler() # 创建标准化对象
X = scaler.fit_transform(X) # 对特征数据进行标准化处理# 定义逻辑回归类
class LogisticRegression:def __init__(self, learning_rate=0.01, num_iterations=1000):self.learning_rate = learning_rate # 设置学习率,默认值为0.01self.num_iterations = num_iterations # 设置迭代次数,默认值为1000self.weights = None # 初始化权重为Noneself.bias = None # 初始化偏置为None# Sigmoid 函数(改进版本,避免溢出)def sigmoid(self, z):z = np.clip(z, -500, 500) # 限制输入值范围,防止计算溢出return 1 / (1 + np.exp(-z)) # 计算Sigmoid函数值# 训练模型方法def fit(self, X, y):# 初始化权重和偏置n_samples, n_features = X.shape # 获取样本数和特征数self.weights = np.zeros(n_features) # 权重初始化为0self.bias = 0 # 偏置初始化为0# 梯度下降优化for i in range(self.num_iterations): # 迭代指定次数# 计算线性组合linear_model = np.dot(X, self.weights) + self.bias# 通过 Sigmoid 函数得到预测概率y_predicted = self.sigmoid(linear_model)# 计算梯度dw = (1 / n_samples) * np.dot(X.T, (y_predicted - y)) # 权重梯度db = (1 / n_samples) * np.sum(y_predicted - y) # 偏置梯度# 更新权重和偏置self.weights -= self.learning_rate * dw # 根据梯度更新权重self.bias -= self.learning_rate * db # 根据梯度更新偏置# 预测函数def predict(self, X):linear_model = np.dot(X, self.weights) + self.bias # 计算线性组合y_predicted = self.sigmoid(linear_model) # 转换为概率# 将概率转换为类别(大于 0.5 划为类别 1,否则划为类别 0)y_predicted_cls = [1 if i > 0.5 else 0 for i in y_predicted]return np.array(y_predicted_cls) # 返回预测类别# 创建逻辑回归实例并训练
model = LogisticRegression(learning_rate=0.01, num_iterations=1000) # 创建模型实例
model.fit(X, y) # 使用训练数据拟合模型# 测试新数据
new_data = np.array([[3000, 2, 0], # 预测这个账号是否存在安全风险[1500, 0, 1]
])# 对新数据进行标准化处理
new_data_scaled = scaler.transform(new_data) # 使用训练集的标准化参数对新数据进行标准化# 预测结果
predictions = model.predict(new_data_scaled) # 对新数据进行预测# 输出预测结果
for i in range(len(new_data)):print(f"账号 {i + 1} 特征:最近登录时间间隔 {new_data[i, 0]} 秒,地点变更次数 {new_data[i, 1]} 次,双重认证 {'开启' if new_data[i, 2] == 1 else '未开启'}")print(f"预测结果:{'存在安全风险' if predictions[i] == 1 else '不存在安全风险'}\n")# 绘制决策边界(简化为二维特征可视化)
plt.figure(figsize=(10, 6)) # 设置图像大小# 绘制已知数据点
plt.scatter(X[y == 0][:, 0], X[y == 0][:, 1], color='green', label='不存在安全风险') # 绘制没有风险的点
plt.scatter(X[y == 1][:, 0], X[y == 1][:, 1], color='red', label='存在安全风险') # 绘制存在风险的点# 计算决策边界
x_values = np.linspace(-2, 2, 2) # 生成x轴的值
y_values = (-model.bias - model.weights[0] * x_values) / model.weights[1] # 计算对应的y值# 绘制决策边界
plt.plot(x_values, y_values, label='决策边界') # 绘制决策边界线plt.xlabel('标准化的最近一次登录距离上次登录的时间间隔(秒)') # 设置x轴标签
plt.ylabel('标准化的最近一次登录的地点变更次数') # 设置y轴标签
plt.title('游戏账号安全风险预测') # 设置图像标题
plt.legend() # 显示图例
plt.show() # 显示图像
账号 1 特征:最近登录时间间隔 3000 秒,地点变更次数 2 次,双重认证 未开启
预测结果:存在安全风险账号 2 特征:最近登录时间间隔 1500 秒,地点变更次数 0 次,双重认证 开启
预测结果:不存在安全风险
案例:客户购买预测
一个市场营销中的客户购买预测场景。逻辑回归模型根据客户的年龄和年收入来预测客户是否会购买产品。
在这个模拟案例中:
-
我们首先生成了模拟数据,年龄范围从 18 到 65 岁,年收入从 2 万到 15 万元
-
使用年龄和年收入作为特征,通过逻辑函数计算购买概率
-
根据概率生成二元购买决策 (0 = 未购买,1 = 购买)
-
将数据分为训练集和测试集,训练逻辑回归模型
-
评估模型性能,包括准确率、混淆矩阵和分类报告
-
可视化决策边界和数据分布,直观展示模型预测效果
-
accuracy_score
- 作用 :用于计算分类模型的准确率。准确率是被正确分类的样本数占总样本数的比例。它是一个常用的评估指标,用于衡量模型在所有测试样本中预测正确的总体比例。
- 简单解释场景 :假设你有一个二分类问题,模型预测了 100 个样本,其中有 80 个预测正确,20 个预测错误。那么
accuracy_score
就是 80/100 = 0.8,即准确率为 80%。它能够直观地反映出模型在整体上的正确预测能力。
-
confusion_matrix
- 作用 :生成混淆矩阵。混淆矩阵是一个表格,用于展示模型的实际类别和预测类别之间的关系。对于二分类问题,它是一个 2×2 的矩阵,其中包括真正例(True Positive)、假正例(False Positive)、真负例(True Negative)和假负例(False Negative)四个部分。
- 简单解释场景 :在二分类中,行代表实际类别,列代表预测类别。例如,第一行第一列表示实际为正类且预测为正类的样本数(真正例),第一行第二列表示实际为正类但预测为负类的样本数(假负例),第二行第一列表示实际为负类但预测为正类的样本数(假正例),第二行第二列表示实际为负类且预测为负类的样本数(真负例)。通过混淆矩阵,可以更详细地了解模型在各个类别上的预测表现,而不仅仅是简单的准确率。
-
classification_report
- 作用 :生成一个包含多个评估指标的报告,包括精确率(Precision)、召回率(Recall)和 F1 - 分数(F1 - Score)等。这些指标可以从不同的角度评估分类模型的性能。
- 简单解释场景 :
- 精确率 :精确率是被正确预测为正类的样本数占所有被预测为正类的样本数的比例。例如,在预测正类的样本中有 50 个,其中实际是正类的有 40 个,那么精确率就是 40/50 = 0.8。它关注的是模型在预测为正类的样本中正确的比例。
- 召回率 :召回率是被正确预测为正类的样本数占所有实际为正类的样本数的比例。例如,实际有 100 个正类样本,模型正确预测了 70 个,那么召回率就是 70/100 = 0.7。它关注的是模型能够正确识别出多少实际的正类样本。
- F1 - 分数 :F1 - 分数是精确率和召回率的调和平均数,公式为 2×(精确率×召回率)/(精确率 + 召回率)。它综合考虑了精确率和召回率,用于平衡两者的关系。
classification_report
可以为每个类别(在多分类任务中)和整体(包括宏平均和微平均等统计方式)提供这些评估指标,帮助用户全面了解模型的分类性能。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report# 设置随机种子,确保结果可复现
np.random.seed(42)# 模拟生成客户购买行为数据
def generate_customer_data(n_samples=200):"""生成模拟的客户购买行为数据参数:n_samples: 样本数量返回:X: 特征矩阵,包含年龄和年收入y: 目标变量,是否购买(0=未购买, 1=购买)"""# 随机生成年龄(18-65岁)和年收入(2万-15万)age = np.random.randint(18, 66, n_samples)income = np.random.uniform(20000, 150000, n_samples)# 创建特征矩阵X = np.column_stack((age, income))# 计算购买概率,受年龄和收入影响# 年龄越大、收入越高,购买概率越高log_odds = -5 + 0.05 * age + 0.0001 * incomeprobability = 1 / (1 + np.exp(-log_odds))# 根据概率确定是否购买y = np.random.binomial(1, probability)return X, y# 生成数据
X, y = generate_customer_data()# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)# 创建并训练逻辑回归模型,明确指定求解器并设置静默模式
model = LogisticRegression(solver='lbfgs', verbose=0) # verbose=0 替代已弃用的 disp=False
model.fit(X_train, y_train)# 在测试集上进行预测
y_pred = model.predict(X_test)# 评估模型性能
accuracy = accuracy_score(y_test, y_pred)
conf_matrix = confusion_matrix(y_test, y_pred)
class_report = classification_report(y_test, y_pred)# 输出评估结果
print(f"模型准确率: {accuracy:.2f}")
print("\n混淆矩阵:")
print(conf_matrix)
print("\n分类报告:")
print(class_report)# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 可视化决策边界和数据点
plt.figure(figsize=(10, 6))# 绘制散点图,颜色表示是否购买,大小表示年收入
plt.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap='bwr', alpha=0.6,s=X_test[:, 1] / 1000, edgecolors='k')# 绘制决策边界
x_min, x_max = X_test[:, 0].min() - 5, X_test[:, 0].max() + 5
y_min, y_max = X_test[:, 1].min() - 10000, X_test[:, 1].max() + 10000
xx, yy = np.meshgrid(np.arange(x_min, x_max, 1),np.arange(y_min, y_max, 1000))Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.3, cmap='bwr')plt.xlabel('年龄')
plt.ylabel('年收入 (元)')
plt.title('逻辑回归客户购买预测模型')
plt.colorbar(label='预测购买概率')
plt.grid(True, linestyle='--', alpha=0.7)# 添加图例
plt.scatter([], [], c='blue', alpha=0.6, s=50, edgecolors='k', label='未购买')
plt.scatter([], [], c='red', alpha=0.6, s=50, edgecolors='k', label='购买')
plt.legend(loc='upper right')plt.tight_layout()
plt.show()# 输出模型系数,解释特征重要性
print("\n模型系数:")
print(f"年龄系数: {model.coef_[0][0]:.4f}")
print(f"年收入系数: {model.coef_[0][1]:.8f}")
print(f"截距: {model.intercept_[0]:.4f}")
模型准确率: 0.95混淆矩阵:
[[ 2 0][ 3 55]]分类报告:precision recall f1-score support0 0.40 1.00 0.57 21 1.00 0.95 0.97 58accuracy 0.95 60macro avg 0.70 0.97 0.77 60
weighted avg 0.98 0.95 0.96 60
模型系数:
年龄系数: 0.0351
年收入系数: 0.00008307
截距: -3.8937
案例:医学上判断病人是否患病
医学上判断病人是否患病:医生可以根据病人的各项身体指标,如血压、血糖、胆固醇含量、白细胞数量等,利用逻辑回归模型来判断病人是否患有某种疾病。
例如,对于糖尿病的诊断,将血压、血糖等指标输入模型,模型会输出患病的概率,若概率大于 0.5,则判断病人可能患有糖尿病。
# 导入需要的库
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split # 用于划分训练集和测试集
from sklearn.metrics import accuracy_score # 用于评估模型准确率
import matplotlib.pyplot as plt# 模拟数据:血压(mmHg)、血糖(mmol/L)、胆固醇(mmol/L)和患病情况(1为患病,0为未患病)
np.random.seed(0)
blood_pressure = np.random.normal(120, 10, 200) # 生成200个均值120,标准差10的血压数据
blood_sugar = np.random.normal(5.5, 1, 200) # 生成200个均值5.5,标准差1的血糖数据
cholesterol = np.random.normal(5.2, 0.8, 200) # 生成200个均值5.2,标准差0.8的胆固醇数据# 设定患病概率与各项指标的关系,指标越高,患病概率越大
log_odds = 0.05 * blood_pressure + 0.8 * blood_sugar + 0.6 * cholesterol - 12 # 线性组合
probability = 1 / (1 + np.exp(-log_odds)) # 通过sigmoid函数转换为概率
# 根据概率生成患病情况,概率大于0.5则患病
disease = np.where(probability > 0.5, 1, 0)# 整理数据为DataFrame
data = pd.DataFrame({'blood_pressure': blood_pressure, 'blood_sugar': blood_sugar,'cholesterol': cholesterol, 'disease': disease})# 划分特征和目标变量
X = data[['blood_pressure', 'blood_sugar', 'cholesterol']]
y = data['disease']# 划分训练集和测试集,测试集占30%
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)# 创建逻辑回归模型
model = LogisticRegression()# 训练模型
model.fit(X_train, y_train)# 输出模型系数和截距
print('模型系数(blood_pressure, blood_sugar, cholesterol):', model.coef_)
print('模型截距:', model.intercept_)# 在测试集上进行预测
y_pred = model.predict(X_test)# 计算模型准确率
accuracy = accuracy_score(y_test, y_pred)
print('模型准确率:', accuracy)# 预测新数据,假设一个人血压130mmHg,血糖7mmol/L,胆固醇6mmol/L
new_data = pd.DataFrame({'blood_pressure': [130], 'blood_sugar': [7], 'cholesterol': [6]})
predicted_prob = model.predict_proba(new_data) # 预测患病和未患病的概率
print('患病概率:', predicted_prob[0][1], ',未患病概率:', predicted_prob[0][0])
print('预测结果(1为患病,0为未患病):', model.predict(new_data)[0])# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 可视化血糖与患病概率的关系
plt.scatter(data['blood_sugar'], data['disease'], label='实际患病情况')
# 计算基于血糖的预测概率(其他特征取平均值)
avg_bp = data['blood_pressure'].mean()
avg_chol = data['cholesterol'].mean()
# 构造用于预测的数据集
X_plot = pd.DataFrame({'blood_pressure': [avg_bp] * len(data), 'blood_sugar': data['blood_sugar'],'cholesterol': [avg_chol] * len(data)})
# 预测概率
pred_prob_plot = model.predict_proba(X_plot)[:, 1]
plt.plot(data['blood_sugar'], pred_prob_plot, color='red', label='预测患病概率')
plt.xlabel('血糖(mmol/L)')
plt.ylabel('患病情况/概率')
plt.title('血糖与患病关系')
plt.legend()
plt.show()
模型系数(blood_pressure, blood_sugar, cholesterol): [[0.22273746 2.26050614 2.03512285]]
模型截距: [-44.3304662]
模型准确率: 0.95
患病概率: 0.9999968233613026 ,未患病概率: 3.1766386974219074e-06
预测结果(1为患病,0为未患病): 1
案例:水果供应链管理
在水果供应链管理中,损耗量是影响利润的关键因素。
本场景通过逻辑回归模型,利用五种水果(樱桃、芒果、香蕉、番石榴、荔枝)的进货量数据,预测某次进货的损耗量是否会 “过高”(高于平均值)。
商户可根据预测结果调整进货策略:若预测为高损耗,可减少对应水果的进货量或加强保鲜措施,从而降低损失。
代码运行说明
- 依赖安装:需安装pandas、scikit-learn、matplotlib、seaborn,可通过pip install pandas scikit-learn matplotlib seaborn安装。
- 数据路径:确保Fruits.csv与代码在同一目录,或修改pd.read_csv()中的路径。
- 结果解读:
- 模型评估指标(准确率、AUC)反映预测效果,越高说明模型越可靠。
- 特征系数可指导进货策略:系数为正的水果,进货量增加会提高高损耗风险;系数为负则相反。
- 实际应用示例可直接替换new_data中的数值,预测新进货的损耗风险。
通过该模型,水果经销商可根据进货量提前预判损耗风险,优化库存策略,降低运营成本。
# 1. 导入必要的库
import pandas as pd # 用于数据读取和处理
import numpy as np # 用于数值计算
import matplotlib.pyplot as plt # 用于可视化
import seaborn as sns # 用于更美观的可视化
from sklearn.model_selection import train_test_split # 划分训练集和测试集
from sklearn.linear_model import LogisticRegression # 逻辑回归模型
from sklearn.preprocessing import StandardScaler # 特征标准化工具
from sklearn.metrics import (accuracy_score, confusion_matrix,classification_report, roc_curve, auc) # 模型评估指标# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置字体为黑体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题# 2. 读取数据
# 假设Fruits.csv与代码在同一文件夹,若不在需指定完整路径(如'data/Fruits.csv')
df = pd.read_csv('./data/Fruits.csv')# 3. 数据理解与预处理
# 查看数据基本结构(前5行),确认列名和数据格式
print("===== 数据预览 =====")
print(df.head()) # 输出前5行数据# 查看数据规模和缺失值情况(确保数据完整)
print("\n===== 数据基本信息 =====")
print(f"数据集共 {df.shape[0]} 行,{df.shape[1]} 列") # 输出行数和列数
print("缺失值统计:")
print(df.isnull().sum()) # 统计每列缺失值,若有缺失需处理(本数据无缺失)# 4. 定义目标变量和特征变量
# 目标变量y:将损耗量(Wastage)二值化(1=高损耗,0=低损耗)
# 以损耗量的平均值作为阈值,高于平均值为"高损耗"
threshold = df['Wastage'].mean() # 计算损耗量平均值
y = (df['Wastage'] > threshold).astype(int) # 转换为0-1变量(1表示高损耗)# 特征变量X:使用五种水果的进货量作为输入特征
X = df[['Cherry', 'Mango', 'Banana', 'Guava', 'Litchi']]# 查看目标变量分布,确认类别是否平衡
print("\n===== 目标变量分布 =====")
print(y.value_counts()) # 输出0和1的数量,若不平衡需调整采样策略
sns.countplot(x=y) # 可视化类别分布
plt.title('高损耗(1)与低损耗(0)样本分布')
plt.show()# 5. 划分训练集和测试集
# 按7:3比例划分,random_state=42确保结果可复现
X_train, X_test, y_train, y_test = train_test_split(X, y,test_size=0.3, # 测试集占30%random_state=42 # 随机种子,保证每次运行结果一致
)# 6. 特征标准化
# 逻辑回归受特征尺度影响大,需将特征标准化(均值=0,方差=1)
scaler = StandardScaler() # 初始化标准化工具
X_train_scaled = scaler.fit_transform(X_train) # 用训练集拟合并转换
X_test_scaled = scaler.transform(X_test) # 用训练集的参数转换测试集(避免数据泄露)# 7. 训练逻辑回归模型
# 初始化模型,设置最大迭代次数(确保收敛)和随机种子
model = LogisticRegression(max_iter=1000, random_state=42)
model.fit(X_train_scaled, y_train) # 用训练数据训练模型# 8. 模型预测与评估
# 在测试集上进行预测
y_pred = model.predict(X_test_scaled) # 预测类别(0或1)
y_pred_proba = model.predict_proba(X_test_scaled)[:, 1] # 预测为"高损耗"的概率# 计算准确率(整体预测正确率)
accuracy = accuracy_score(y_test, y_pred)
print(f"\n===== 模型评估 =====")
print(f"测试集准确率:{accuracy:.4f}") # 输出准确率,保留4位小数# 输出混淆矩阵(详细展示预测对错情况)
print("\n混淆矩阵:")
cm = confusion_matrix(y_test, y_pred)
# 可视化混淆矩阵
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',xticklabels=['低损耗', '高损耗'],yticklabels=['低损耗', '高损耗'])
plt.xlabel('预测结果')
plt.ylabel('实际结果')
plt.title('混淆矩阵')
plt.show()# 输出分类报告(包含精确率、召回率、F1分数)
print("\n分类报告:")
print(classification_report(y_test, y_pred, target_names=['低损耗', '高损耗']))# 绘制ROC曲线并计算AUC(评估模型区分能力)
fpr, tpr, _ = roc_curve(y_test, y_pred_proba)
roc_auc = auc(fpr, tpr)
plt.figure()
plt.plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC曲线 (AUC = {roc_auc:.4f})')
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--') # 随机猜测的基准线
plt.xlabel('假正例率')
plt.ylabel('真正例率')
plt.title('ROC曲线')
plt.legend()
plt.show()# 9. 模型解释(分析特征对损耗的影响)
# 提取特征系数,系数越大表示该特征对"高损耗"的贡献越大
coefficients = pd.DataFrame({'水果种类': X.columns, # 特征名称(水果种类)'影响系数': model.coef_[0] # 逻辑回归系数
})
# 按系数绝对值排序,查看影响最大的特征
coefficients['系数绝对值'] = coefficients['影响系数'].abs()
coefficients = coefficients.sort_values(by='系数绝对值', ascending=False)print("\n===== 特征影响分析 =====")
print(coefficients[['水果种类', '影响系数']]) # 输出特征及其影响系数
# 可视化特征系数
sns.barplot(x='影响系数', y='水果种类', data=coefficients)
plt.title('各水果进货量对高损耗的影响系数')
plt.axvline(x=0, color='gray', linestyle='--') # 参考线(系数=0)
plt.show()# 10. 实际应用示例(预测新进货数据的损耗风险)
print("\n===== 应用示例 =====")
# 假设新进货数据(单位:kg)
new_data = pd.DataFrame({'Cherry': [30000], # 樱桃进货30000kg'Mango': [25000], # 芒果进货25000kg'Banana': [40000], # 香蕉进货40000kg'Guava': [15000], # 番石榴进货15000kg'Litchi': [20000] # 荔枝进货20000kg
})
# 对新数据进行标准化(使用训练好的scaler)
new_data_scaled = scaler.transform(new_data)
# 预测损耗风险
pred = model.predict(new_data_scaled)
pred_proba = model.predict_proba(new_data_scaled)[0, 1]# 输出预测结果
if pred[0] == 1:print(f"新进货预测为【高损耗】,概率:{pred_proba:.2%},建议减少进货量或加强保鲜!")
else:print(f"新进货预测为【低损耗】,概率:{1 - pred_proba:.2%},可按计划进货。")
===== 数据预览 =====Unnamed: 0 Cherry Mango Banana Guava Litchi Wastage
0 0 30153 45568 42342 23946 15399 19466
1 1 13003 29345 34255 19097 34973 7116
2 2 6619 12263 2710 6462 7689 25064
3 3 32956 32519 1548 45711 35422 19784
4 4 42122 16142 37817 42599 10118 44063===== 数据基本信息 =====
数据集共 3600 行,7 列
缺失值统计:
Unnamed: 0 0
Cherry 0
Mango 0
Banana 0
Guava 0
Litchi 0
Wastage 0
dtype: int64===== 目标变量分布 =====
Wastage
0 1839
1 1761
Name: count, dtype: int64
===== 模型评估 =====
测试集准确率:0.4954混淆矩阵:
分类报告:precision recall f1-score support低损耗 0.50 0.67 0.58 549高损耗 0.48 0.31 0.38 531accuracy 0.50 1080macro avg 0.49 0.49 0.48 1080
weighted avg 0.49 0.50 0.48 1080
===== 特征影响分析 =====水果种类 影响系数
3 Guava 0.078359
1 Mango 0.030900
2 Banana 0.007975
4 Litchi 0.003001
0 Cherry -0.002988
===== 应用示例 =====
新进货预测为【低损耗】,概率:53.13%,可按计划进货。
案例:癌症患者生存状态预测
该场景基于中国癌症患者数据集(china_cancer_patients_synthetic.csv),通过逻辑回归算法预测癌症患者的生存状态(Alive/Deceased)。
核心价值在于:
- 辅助临床医生根据患者特征(如年龄、肿瘤类型、分期、治疗方式等)评估预后风险;
- 识别影响患者生存的关键因素(如肿瘤大小、是否转移、治疗类型等);
- 为个性化治疗方案制定提供数据支持。
# 1. 导入必要的库
import pandas as pd # 用于数据处理和分析
import numpy as np # 用于数值计算
from sklearn.model_selection import train_test_split # 用于拆分训练集和测试集
from sklearn.preprocessing import OneHotEncoder, StandardScaler # 用于特征编码和标准化
from sklearn.compose import ColumnTransformer # 用于对不同类型特征应用不同预处理
from sklearn.pipeline import Pipeline # 用于构建预处理和模型的流水线
from sklearn.linear_model import LogisticRegression # 逻辑回归模型
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix # 模型评估指标
import warningswarnings.filterwarnings('ignore') # 忽略警告信息,避免干扰输出# 2. 读取CSV文件
# 假设文件路径为当前工作目录下的"china_cancer_patients_synthetic.csv"
df = pd.read_csv("./data/china_cancer_patients_synthetic.csv")# 3. 数据预处理
# 3.1 查看数据基本信息(可选,用于调试)
print("数据集基本信息:")
print(f"样本数量:{df.shape[0]}, 特征数量:{df.shape[1]}")
print("前5行数据:")
print(df.head())# 3.2 选择特征变量(X)和目标变量(y)
# 目标变量:SurvivalStatus(Alive=1, Deceased=0)
y = df["SurvivalStatus"].map({"Alive": 1, "Deceased": 0})# 特征变量:选择可能影响生存状态的特征(排除ID、日期等无关特征)
features = ["Gender", "Age", "Province", "Ethnicity", "TumorType","CancerStage", "TumorSize", "Metastasis", "TreatmentType","ChemotherapySessions", "RadiationSessions", "SmokingStatus","AlcoholUse", "GeneticMutation", "Comorbidities"
]
X = df[features]# 3.3 处理缺失值(填充分类特征为"Unknown",数值特征为均值)
# 分离分类特征和数值特征
categorical_features = ["Gender", "Province", "Ethnicity", "TumorType","CancerStage", "Metastasis", "TreatmentType","SmokingStatus", "AlcoholUse", "GeneticMutation", "Comorbidities"]
numeric_features = ["Age", "TumorSize", "ChemotherapySessions", "RadiationSessions"]# 填充缺失值
X[categorical_features] = X[categorical_features].fillna("Unknown")
X[numeric_features] = X[numeric_features].fillna(X[numeric_features].mean())# 4. 特征预处理流水线
# 分类特征:独热编码(One-Hot Encoding)
# 数值特征:标准化(StandardScaling)
preprocessor = ColumnTransformer(transformers=[('num', StandardScaler(), numeric_features), # 数值特征标准化('cat', OneHotEncoder(handle_unknown='ignore'), categorical_features) # 分类特征独热编码])# 5. 划分训练集和测试集(7:3比例)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y # stratify=y保证训练集和测试集的目标变量分布一致
)# 6. 构建逻辑回归模型流水线(预处理+模型)
# 使用lbfgs solver,适合二分类问题;增加max_iter确保收敛
model = Pipeline([('preprocessor', preprocessor),('classifier', LogisticRegression(solver='lbfgs', max_iter=1000, random_state=42))
])# 7. 训练模型
model.fit(X_train, y_train)# 8. 模型预测与评估
# 8.1 在测试集上预测
y_pred = model.predict(X_test)# 8.2 计算评估指标
accuracy = accuracy_score(y_test, y_pred)
print(f"\n模型准确率:{accuracy:.4f}")print("\n混淆矩阵:")
print(confusion_matrix(y_test, y_pred))print("\n分类报告(Precision/Recall/F1):")
print(classification_report(y_test, y_pred))# 9. 提取特征重要性(针对数值特征和编码后的分类特征)
# 注意:独热编码后的特征重要性需要与原始特征对应
if hasattr(model['classifier'], 'coef_'):# 获取特征名称(数值特征+独热编码后的分类特征)ohe = model['preprocessor'].named_transformers_['cat']cat_feature_names = list(ohe.get_feature_names_out(categorical_features))all_feature_names = numeric_features + cat_feature_names# 提取系数(重要性)coefficients = pd.DataFrame(model['classifier'].coef_[0],index=all_feature_names,columns=['Coefficient']).sort_values(by='Coefficient', ascending=False)print("\nTop 10 正向影响特征(系数从大到小):")print(coefficients.head(10))print("\nTop 10 负向影响特征(系数从小到大):")print(coefficients.tail(10))
数据集基本信息:
样本数量:10000, 特征数量:20
前5行数据:PatientID Gender Age Province Ethnicity TumorType CancerStage \
0 CHN-00001 Male 32 Hunan Han Lung I
1 CHN-00002 Male 66 Sichuan Han Lung IV
2 CHN-00003 Other 26 Guangdong Han Lung III
3 CHN-00004 Other 35 Anhui Uyghur Breast III
4 CHN-00005 Male 32 Guangdong Han Stomach II DiagnosisDate TumorSize Metastasis TreatmentType SurgeryDate \
0 2010-07-24 8.2 No Radiation 2010-08-24
1 2015-01-03 9.5 Yes Chemotherapy 2015-03-24
2 2022-03-26 9.3 Yes Surgery 2022-07-14
3 2019-06-19 7.7 No Surgery 2019-08-27
4 2012-02-07 7.3 No Chemotherapy NaN ChemotherapySessions RadiationSessions SurvivalStatus FollowUpMonths \
0 0 23 Alive 44
1 11 0 Deceased 57
2 0 0 Alive 40
3 0 0 Deceased 45
4 4 0 Alive 42 SmokingStatus AlcoholUse GeneticMutation Comorbidities
0 Current NaN NaN NaN
1 Never Occasional EGFR Hepatitis B, Hypertension
2 Former NaN NaN NaN
3 Never Occasional KRAS NaN
4 Never NaN NaN NaN 模型准确率:0.7703混淆矩阵:
[[ 328 335][ 354 1983]]分类报告(Precision/Recall/F1):precision recall f1-score support0 0.48 0.49 0.49 6631 0.86 0.85 0.85 2337accuracy 0.77 3000macro avg 0.67 0.67 0.67 3000
weighted avg 0.77 0.77 0.77 3000Top 10 正向影响特征(系数从大到小):Coefficient
CancerStage_II 3.474690
CancerStage_I 3.260486
Comorbidities_Hypertension, Hepatitis B 0.604964
Metastasis_No 0.524937
Ethnicity_Other 0.428554
Metastasis_Yes 0.391382
AlcoholUse_Heavy 0.375424
SmokingStatus_Former 0.367049
Province_Hebei 0.334942
Ethnicity_Zhuang 0.331630Top 10 负向影响特征(系数从小到大):Coefficient
Age -0.050922
Comorbidities_Hepatitis B, Diabetes -0.053902
Province_Jiangsu -0.058410
Comorbidities_Unknown -0.070690
Ethnicity_Hui -0.078426
Ethnicity_Han -0.116946
Province_Shandong -0.163059
Province_Qinghai -0.324557
CancerStage_IV -2.867474
CancerStage_III -2.951384