我的Logistic Regression模型持续输出相同预测结果,原因何在?
问题分析与解决
使用糖尿病数据集构建Logistic Regression模型时,无论输入何种参数均输出“Diabetes”,核心问题及修正方案如下:
核心问题
- 预测输入未做归一化:训练时用
MinMaxScaler将特征缩放到[0,1]区间,但预测时直接传入原始数值,特征尺度与训练数据完全不符,导致模型输出异常。 - K折交叉验证使用错误:当前代码中Kfold循环仅保留最后一次划分的训练/测试集,未实现交叉验证的评估逻辑,反而增加变量覆盖风险。
- 全局变量滥用:大量使用全局变量存储模型、数据等,易引发逻辑混乱和变量意外覆盖。
修正后的代码
import pandas as pd from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import MinMaxScaler from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score from sklearn.model_selection import KFold class DiabetesLogReg: def __init__(self, p, g, bp, st, i, bmi, dpf, age): # 初始化用户输入特征 self.preg = p self.glucose = g self.bp = bp self.skin_thickness = st self.insulin = i self.bmi = bmi self.diabetes_pedigree = dpf self.age = age # 读取数据集 self.df = pd.read_csv("/Users/aahan_bagga/Desktop/diabetes_data.csv") self.X = self.df.drop(["Outcome"], axis=1) self.Y = self.df["Outcome"] # 初始化模型与归一化器 self.scaler = None self.model = None def preprocessing(self): # 单次划分训练/测试集 X_train, X_test, Y_train, Y_test = train_test_split( self.X, self.Y, test_size=0.2, random_state=19, shuffle=True ) # 归一化并保存归一化器 self.scaler = MinMaxScaler() self.x_train_s = self.scaler.fit_transform(X_train) self.x_test_s = self.scaler.transform(X_test) self.Y_train = Y_train self.Y_test = Y_test def train(self): # 训练模型并保存 self.model = LogisticRegression(max_iter=2000) self.model.fit(self.x_train_s, self.Y_train) y_pred = self.model.predict(self.x_test_s) return f"{accuracy_score(self.Y_test, y_pred) * 100:.1f}%" def diabetes_pred(self): # 构造输入特征并做归一化转换 input_features = [ [self.preg, self.glucose, self.bp, self.skin_thickness, self.insulin, self.bmi, self.diabetes_pedigree, self.age] ] input_scaled = self.scaler.transform(input_features) # 预测并返回结果 prob = self.model.predict_proba(input_scaled) print(prob) return "Diabetes" if prob[0,1] > 0.5 else "No Diabetes" def evaluate_with_kfold(self, n_splits=9): # 正确实现K折交叉验证(避免数据泄露) scores = [] kf = KFold(n_splits=n_splits, shuffle=True, random_state=19) for train_idx, test_idx in kf.split(self.X): X_train, X_test = self.X.iloc[train_idx], self.X.iloc[test_idx] Y_train, Y_test = self.Y.iloc[train_idx], self.Y.iloc[test_idx] scaler = MinMaxScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) model = LogisticRegression(max_iter=2000) model.fit(X_train_scaled, Y_train) scores.append(accuracy_score(Y_test, model.predict(X_test_scaled))) avg_score = sum(scores)/len(scores) return f"Average K-fold accuracy: {avg_score*100:.1f}%" # 测试示例 d = DiabetesLogReg(2,126,45,23,340,30,0.12,29) d.preprocessing() print(d.train()) print(d.diabetes_pred()) # 可选:评估K折交叉验证准确率 # print(d.evaluate_with_kfold())
关键修正点说明
- 归一化复用:保存训练时的
MinMaxScaler,预测时用同一转换器处理输入数据,保证特征尺度一致。 - 实例属性替代全局变量:用
self.xxx存储模型、数据、归一化器,避免全局变量引发的逻辑混乱。 - 正确的K折交叉验证:在每个折内单独拟合归一化器,避免数据泄露,同时计算平均准确率评估模型性能。
内容的提问来源于stack exchange,提问作者JiffyTec
相关产品推荐
相关产品推荐

