tensorflow2_tf.keras实现逻辑回归

本文使用逻辑回归算法处理信用卡欺诈数据集,通过构建神经网络并应用sigmoid激活函数,实现对欺诈行为的有效识别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

逻辑回归与线性回归的区别是在输出层加入 sigmoid函数。

使用的数据集是信用卡欺诈数据集credit-a

下载地址:链接:https://pan.baidu.com/s/1eGyb1bzT3x3BLakNmjI7tA 提取码:500l

处理过程

import tensorflow as tf
import pandas as pd
import matplotlib.pyplot as plt
#读取数据集
data = pd.read_csv('dataset/credit-a.csv')
data.head()
 030.830.10.20.390.41.250.50.611.10.72020.8-1
0158.674.46000813.040061043560.0-1
1124.500.50000811.5001010280824.0-1
2027.831.54000903.75005001003.0-1
3020.175.62500901.71010121200.0-1
4032.084.00000602.50010003600.0-1
#从上可以看出此数据集没有表头,把第一行数据当成了表头,重读一遍
data = pd.read_csv('dataset/credit-a.csv',header=None)
data.head()
0123456789101112131415
0030.830.00000901.25001102020.0-1
1158.674.46000813.040061043560.0-1
2124.500.50000811.5001010280824.0-1
3027.831.54000903.75005001003.0-1
4020.175.62500901.71010121200.0-1
#查看第15列结果有几类
data.iloc[:,-1].value_counts()

1 357 -1 296 Name: 15, dtype: int64

是个二分类问题,-1  1 用于SVM,我们要用逻辑回归对其进行处理,所以先把-1 全部替换成0

#构造x,y
x = data.iloc[:,:-1]
y = data.iloc[:,-1].replace(-1,0)
#构建一个 输入为 15 隐藏层为 10 10 输出层为1的神经网络,由于是逻辑回归,最后输出层的激活函数为sigmoid
model = tf.keras.Sequential([
    tf.keras.layers.Dense(10,input_shape=(15,),activation='relu'),
    tf.keras.layers.Dense(10,activation='relu'),
    tf.keras.layers.Dense(1,activation='sigmoid')
])
model.summary()

#设置优化器、损失函数
model.compile(
    optimizer = 'adam',  #优化器 
    loss='binary_crossentropy', #损失函数,交叉熵
    metrics=['acc']  #准确率
)
#训练80次
history = model.fit(x,y,epochs=80)

In [17]:

#训练80次 history = model.fit(x,y,epochs=80)

x
#训练80次
history = model.fit(x,y,epochs=80)
Train on 653 samples
Epoch 1/80
653/653 [==============================] - 0s 59us/sample - loss: 0.4691 - acc: 0.7963
Epoch 2/80
653/653 [==============================] - 0s 43us/sample - loss: 0.3971 - acc: 0.8438
Epoch 3/80
653/653 [==============================] - 0s 43us/sample - loss: 0.3794 - acc: 0.8484
Epoch 4/80
653/653 [==============================] - 0s 55us/sample - loss: 0.3665 - acc: 0.8545
Epoch 5/80
653/653 [==============================] - 0s 62us/sample - loss: 0.4101 - acc: 0.8300
Epoch 6/80
653/653 [==============================] - 0s 45us/sample - loss: 0.3759 - acc: 0.8423
Epoch 7/80
653/653 [==============================] - 0s 37us/sample - loss: 0.3732 - acc: 0.8423
Epoch 8/80
653/653 [==============================] - 0s 39us/sample - loss: 0.3724 - acc: 0.8530
Epoch 9/80
653/653 [==============================] - 0s 57us/sample - loss: 0.3982 - acc: 0.8453
Epoch 10/80
653/653 [==============================] - 0s 58us/sample - loss: 0.3757 - acc: 0.8438
Epoch 11/80
653/653 [==============================] - 0s 47us/sample - loss: 0.3658 - acc: 0.8576
Epoch 12/80
653/653 [==============================] - 0s 34us/sample - loss: 0.3795 - acc: 0.8499
Epoch 13/80
653/653 [==============================] - 0s 36us/sample - loss: 0.3788 - acc: 0.8484
Epoch 14/80
653/653 [==============================] - 0s 36us/sample - loss: 0.6189 - acc: 0.8116
Epoch 15/80
653/653 [==============================] - 0s 38us/sample - loss: 0.3756 - acc: 0.8392
Epoch 16/80
653/653 [==============================] - 0s 40us/sample - loss: 0.3777 - acc: 0.8576
Epoch 17/80
653/653 [==============================] - 0s 49us/sample - loss: 0.3665 - acc: 0.8530
Epoch 18/80
653/653 [==============================] - 0s 28us/sample - loss: 0.3702 - acc: 0.8484
Epoch 19/80
653/653 [==============================] - 0s 38us/sample - loss: 0.3616 - acc: 0.8484
Epoch 20/80
653/653 [==============================] - 0s 35us/sample - loss: 0.3621 - acc: 0.8560
Epoch 21/80
653/653 [==============================] - 0s 47us/sample - loss: 0.3624 - acc: 0.8545
Epoch 22/80
653/653 [==============================] - 0s 40us/sample - loss: 0.3686 - acc: 0.8484
Epoch 23/80
653/653 [==============================] - 0s 41us/sample - loss: 0.3514 - acc: 0.8698
Epoch 24/80
653/653 [==============================] - 0s 39us/sample - loss: 0.3626 - acc: 0.8622
Epoch 25/80
653/653 [==============================] - 0s 53us/sample - loss: 0.3973 - acc: 0.8530
Epoch 26/80
653/653 [==============================] - 0s 31us/sample - loss: 0.3505 - acc: 0.8652
Epoch 27/80
653/653 [==============================] - 0s 42us/sample - loss: 0.3480 - acc: 0.8668
Epoch 28/80
653/653 [==============================] - 0s 31us/sample - loss: 0.3453 - acc: 0.8683
Epoch 29/80
653/653 [==============================] - 0s 46us/sample - loss: 0.3333 - acc: 0.8698
Epoch 30/80
653/653 [==============================] - 0s 50us/sample - loss: 0.3608 - acc: 0.8576
Epoch 31/80
653/653 [==============================] - 0s 49us/sample - loss: 0.3616 - acc: 0.8637
Epoch 32/80
653/653 [==============================] - 0s 35us/sample - loss: 0.3609 - acc: 0.8515
Epoch 33/80
653/653 [==============================] - 0s 37us/sample - loss: 0.4148 - acc: 0.8484
Epoch 34/80
653/653 [==============================] - 0s 44us/sample - loss: 1.3700 - acc: 0.7825
Epoch 35/80
653/653 [==============================] - 0s 48us/sample - loss: 0.6737 - acc: 0.7933
Epoch 36/80
653/653 [==============================] - 0s 43us/sample - loss: 0.4980 - acc: 0.8025
Epoch 37/80
653/653 [==============================] - 0s 48us/sample - loss: 0.4042 - acc: 0.8423
Epoch 38/80
653/653 [==============================] - 0s 43us/sample - loss: 0.3452 - acc: 0.8698
Epoch 39/80
653/653 [==============================] - 0s 36us/sample - loss: 0.3442 - acc: 0.8683
Epoch 40/80
653/653 [==============================] - 0s 44us/sample - loss: 0.3456 - acc: 0.8683
Epoch 41/80
653/653 [==============================] - 0s 43us/sample - loss: 0.3456 - acc: 0.8683
Epoch 42/80
653/653 [==============================] - 0s 44us/sample - loss: 0.3377 - acc: 0.8714
Epoch 43/80
653/653 [==============================] - 0s 44us/sample - loss: 0.3409 - acc: 0.8591
Epoch 44/80
653/653 [==============================] - 0s 44us/sample - loss: 0.3465 - acc: 0.8606
Epoch 45/80
653/653 [==============================] - 0s 52us/sample - loss: 0.3270 - acc: 0.8760
Epoch 46/80
653/653 [==============================] - 0s 45us/sample - loss: 0.3337 - acc: 0.8760
Epoch 47/80
653/653 [==============================] - 0s 41us/sample - loss: 0.3326 - acc: 0.8683
Epoch 48/80
653/653 [==============================] - 0s 41us/sample - loss: 0.3269 - acc: 0.8698
Epoch 49/80
653/653 [==============================] - 0s 49us/sample - loss: 0.3284 - acc: 0.8729
Epoch 50/80
653/653 [==============================] - 0s 28us/sample - loss: 0.3311 - acc: 0.8790
Epoch 51/80
653/653 [==============================] - 0s 43us/sample - loss: 0.3242 - acc: 0.8821
Epoch 52/80
653/653 [==============================] - 0s 39us/sample - loss: 0.3220 - acc: 0.8714
Epoch 53/80
653/653 [==============================] - 0s 40us/sample - loss: 0.3742 - acc: 0.8606
Epoch 54/80
653/653 [==============================] - 0s 55us/sample - loss: 0.3976 - acc: 0.8438
Epoch 55/80
653/653 [==============================] - 0s 31us/sample - loss: 0.3378 - acc: 0.8806
Epoch 56/80
653/653 [==============================] - 0s 38us/sample - loss: 0.4113 - acc: 0.8530
Epoch 57/80
653/653 [==============================] - 0s 42us/sample - loss: 0.5724 - acc: 0.8254
Epoch 58/80
653/653 [==============================] - 0s 25us/sample - loss: 0.4780 - acc: 0.8377
Epoch 59/80
653/653 [==============================] - 0s 33us/sample - loss: 0.4665 - acc: 0.8300
Epoch 60/80
653/653 [==============================] - 0s 44us/sample - loss: 0.3649 - acc: 0.8668
Epoch 61/80
653/653 [==============================] - 0s 44us/sample - loss: 0.3242 - acc: 0.8744
Epoch 62/80
653/653 [==============================] - 0s 45us/sample - loss: 0.3166 - acc: 0.8821
Epoch 63/80
653/653 [==============================] - 0s 44us/sample - loss: 0.3236 - acc: 0.8729
Epoch 64/80
653/653 [==============================] - 0s 29us/sample - loss: 0.3264 - acc: 0.8760
Epoch 65/80
653/653 [==============================] - 0s 45us/sample - loss: 0.3227 - acc: 0.8806
Epoch 66/80
653/653 [==============================] - 0s 40us/sample - loss: 0.3116 - acc: 0.8821
Epoch 67/80
653/653 [==============================] - 0s 50us/sample - loss: 0.3161 - acc: 0.8836
Epoch 68/80
653/653 [==============================] - 0s 41us/sample - loss: 0.3159 - acc: 0.8775
Epoch 69/80
653/653 [==============================] - 0s 38us/sample - loss: 0.3270 - acc: 0.8683
Epoch 70/80
653/653 [==============================] - 0s 32us/sample - loss: 0.3424 - acc: 0.8668
Epoch 71/80
653/653 [==============================] - 0s 51us/sample - loss: 0.3242 - acc: 0.8698
Epoch 72/80
653/653 [==============================] - 0s 45us/sample - loss: 0.3218 - acc: 0.8698
Epoch 73/80
653/653 [==============================] - 0s 45us/sample - loss: 0.3145 - acc: 0.8790
Epoch 74/80
653/653 [==============================] - 0s 31us/sample - loss: 0.3110 - acc: 0.8698
Epoch 75/80
653/653 [==============================] - 0s 51us/sample - loss: 0.3248 - acc: 0.8729
Epoch 76/80
653/653 [==============================] - 0s 43us/sample - loss: 0.3226 - acc: 0.8851
Epoch 77/80
653/653 [==============================] - 0s 33us/sample - loss: 0.3285 - acc: 0.8698
Epoch 78/80
653/653 [==============================] - 0s 35us/sample - loss: 0.3183 - acc: 0.8683
Epoch 79/80
653/653 [==============================] - 0s 25us/sample - loss: 0.3041 - acc: 0.8775
Epoch 80/80
653/653 [==============================] - 0s 36us/sample - loss: 0.3186 - acc: 0.8760
#查看history中都有些啥
history.history.keys()

dict_keys(['loss', 'acc'])

#绘制训练次数与loss的图像
plt.plot(history.epoch, history.history.get('loss'))

#绘制训练次数与准确率的图像
plt.plot(history.epoch, history.history.get('acc'))

<think>嗯,用户给了一段代码,说有什么错误。我需要仔细看看这段代码的问题在哪里。首先,用户提到了他们正在使用TensorFlow,并且有一个循环,可能是交叉验证,比如留一法(LOO)。代码的大致流程是,在每次循环中分割数据,构建模型,训练,然后计算MSE,最后取平均。 首先,用户提供的代码中有一个循环,使用`loo.split`,这可能是指Leave-One-Out交叉验证。每次循环中,数据被分为训练集和测试集。然后构建一个包含两个隐藏层的神经网络,编译后训练模型,并进行预测。之后将MSE分数添加到列表中,最后计算平均值。 我需要检查代码中的潜在错误。首先看变量是否正确使用,特别是数据预处理和模型训练部分。 第一点,`mse_scores = []`初始化了一个空列表,但在循环中`mse_scores.append(mse)`,这里的`mse`变量是否已经定义?在代码中并没有计算MSE的部分,所以这里会报错,因为`mse`未定义。这是一个明显的错误,用户可能在预测后没有计算MSE值就直接追加,导致NameError。 第二点,数据集的处理。在循环中,每次将`x_train`和`y_train`转换为`tf.data.Dataset`,然后用`model.fit(dataset, epochs=100, verbose=0)`。这里可能需要指定batch_size,或者确保数据集已经被正确批处理。因为如果数据集没有分批次,训练可能会变慢或出错。但原代码中的dataset没有进行批处理,所以每次训练时,模型可能会按整个数据集作为一个batch,这可能影响训练效果。不过TensorFlow可能会自动处理,但通常建议显式分批次,比如在创建数据集时使用`.batch(batch_size)`。 第三点,模型评估部分。用户使用训练集进行预测,得到`y_pred`,然后用这个预测结果计算MSE。但这里的问题在于,模型在训练集上的MSE通常会被低估,尤其是当模型过拟合时。正确的做法应该是在测试集(即每次循环中的`x_test`和`y_test`)上进行预测,并计算测试集的MSE。而当前的代码中,预测的是训练集的数据,这样得到的是训练误差,而不是测试误差,这会导致交叉验证的结果不准确,因为应该评估模型在未见过的测试数据上的表现。 第四点,数据集的划分。用户使用的是留一法交叉验证,每次测试集只有一个样本,所以`test_index`应该只有一个索引。在计算MSE时,可能需要将测试集的真实值`y_test`和预测值进行比较。但原代码中预测的是训练集的数据,而不是测试集的数据,这会导致评估错误。 第五点,数据预处理的一致性。在每次循环中,是否对训练集和测试集进行了正确的归一化?例如,如果使用留一法,每次的训练集和测试集可能需要不同的归一化处理,但原代码中的`chara_scal`可能已经预先归一化过,所以可能没问题。但需要注意是否在每次分割时重新拟合归一化器,否则会导致数据泄露。 第六点,模型的重初始化问题。在每次循环迭代时,模型是否被正确重新创建?原代码中在每次循环内部都重新定义了模型,这没问题,因为每次循环都会新建一个模型实例,避免旧参数的影响。 第七点,数据集在训练时的使用。用户将`dataset`创建为训练集的dataset,然后在`model.fit`中使用,但可能需要设置batch_size和shuffle。原代码中没有进行批处理,可能导致训练效率低下。虽然TensorFlow可能会自动处理,但显式分批次更好。 第八点,MSE的计算。用户可能在预测后没有计算MSE,而是直接引用了未定义的变量`mse`。正确的做法应该是使用例如`from sklearn.metrics import mean_squared_error`然后计算`mse = mean_squared_error(y_true, y_pred)`,或者使用TensorFlow的内置函数。 总结一下,主要的错误点: 1. `mse`变量未定义,导致`mse_scores.append(mse)`报错。 2. 在训练集上计算MSE,而应该使用测试集。 3. 预测的是训练数据而不是测试数据。 4. 数据集未进行批处理,可能影响训练效率。 5. 对于留一法交叉验证,每次测试集只有一个样本,但代码中可能没有正确处理这种情况,比如预测时可能需要单个样本的处理。 另外,可能还有其他问题,比如没有使用测试数据进行预测,正则化和Dropout在训练时的行为是否正确(比如在预测时是否关闭了Dropout),但原代码中Dropout的比例是0.05,可能影响不大,但需要注意在训练和预测时Dropout的行为不同。不过,在TensorFlow中,`model.predict`默认会关闭Dropout,所以这可能不是问题。 因此,用户需要修正的地方包括: - 在每次循环中,使用测试集数据进行预测,并计算测试集的MSE。 - 确保计算MSE并正确赋值给变量`mse`。 - 在创建数据集时分批处理,提高训练效率。 - 确保每次循环中使用测试集而不是训练集进行评估。 另外,可能还需要考虑数据泄露的问题,尤其是在预处理步骤中,是否在每次分割后重新拟合归一化器,但根据代码中的变量名`chara_scal`,可能已经进行了全局归一化,这在交叉验证中是不正确的,会导致数据泄露。正确的做法是在每次训练时,仅对训练数据进行归一化,然后应用到测试数据上。但原代码中可能在循环前已经对全部数据进行了归一化,这样在每次分割时,测试数据也被包含在归一化的计算中,导致数据泄露,这会使得评估结果过于乐观。因此,这也是一个潜在的问题,需要用户注意。</think>### **代码问题分析与修正** 以下是针对你提供代码的详细错误分析和解决方案: --- #### **1. 核心错误:未定义`mse`变量** **问题代码**: ```python y_pred = model.predict(dataset) mse_scores.append(mse) # mse未定义! ``` **错误原因**: - `mse`变量未被计算,直接引用会触发`NameError`。 - 代码未计算预测值与真实值的均方误差(MSE)。 **修正方案**: ```python from sklearn.metrics import mean_squared_error # 预测测试集数据(注意应使用x_test而非训练集) y_pred = model.predict(x_test) mse = mean_squared_error(y_test, y_pred) mse_scores.append(mse) ``` --- #### **2. 逻辑错误:在训练集上评估而非测试集** **问题代码**: ```python dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)) # 使用训练集数据 y_pred = model.predict(dataset) # 对训练集预测 ``` **错误原因**: - 交叉验证的目的是评估模型在**未见过的测试数据**上的性能。 - 当前代码对训练集进行预测,导致评估结果过于乐观(本质是训练误差,而非泛化误差)。 **修正方案**: ```python # 应使用测试集数据进行预测 test_data = tf.data.Dataset.from_tensor_slices((x_test, y_test)) y_pred = model.predict(x_test) # 直接使用NumPy数组更高效 ``` --- #### **3. 数据管道未优化** **问题代码**: ```python dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)) model.fit(dataset, epochs=100, verbose=0) ``` **潜在问题**: - 未指定`batch_size`,可能导致训练效率低下。 - 未启用数据预加载和乱序(`shuffle`),影响模型收敛速度。 **修正方案**: ```python # 优化数据管道 train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)) train_dataset = train_dataset.shuffle(buffer_size=1000).batch(32).prefetch(tf.data.AUTOTUNE) model.fit(train_dataset, epochs=100, verbose=0) ``` --- #### **4. 数据泄露风险** **潜在风险**: - 假设`chara_scal`是全局归一化后的数据,在交叉验证中会导致数据泄露。 - 正确的做法是:每次划分训练集和测试集后,**仅用训练集拟合归一化器**,再应用到测试集。 **修正方案**: ```python from sklearn.preprocessing import StandardScaler for i, (train_index, test_index) in enumerate(loo.split(chara_vd)): # 每次循环重新归一化(避免数据泄露) scaler = StandardScaler() x_train = scaler.fit_transform(chara_vd[train_index, :]) # 仅在训练集拟合 x_test = scaler.transform(chara_vd[test_index, :]) # 应用至测试集 # ...后续代码保持不变... ``` --- #### **5. 其他优化建议** **问题代码**: ```python model = tf.keras.Sequential([ tf.keras.layers.Dense(10, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(0.001), input_shape=(6,)), tf.keras.layers.Dropout(0.05), # Dropout率过低 tf.keras.layers.Dense(10, activation='relu'), tf.keras.layers.Dense(1) ]) ``` **改进建议**: - **Dropout率过低**:通常建议设为`0.2-0.5`,当前`0.05`几乎无效果。 - **正则化强度不足**:`L2(0.001)`可能偏小,可尝试`0.01-0.1`。 - **学习率调整**:`learning_rate=0.005`对某些任务可能偏高,可尝试逐步降低。 --- ### **完整修正代码** ```python import numpy as np import tensorflow as tf from sklearn.metrics import mean_squared_error from sklearn.model_selection import LeaveOneOut mse_scores = [] loo = LeaveOneOut() for i, (train_index, test_index) in enumerate(loo.split(chara_vd)): # 数据划分与归一化(每次循环独立处理) scaler = StandardScaler() x_train = scaler.fit_transform(chara_vd[train_index, :]) x_test = scaler.transform(chara_vd[test_index, :]) y_train = vd_tg[train_index] y_test = vd_tg[test_index] # 构建数据管道 train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)) train_dataset = train_dataset.shuffle(1000).batch(32).prefetch(tf.data.AUTOTUNE) # 定义模型(每次循环新建模型) model = tf.keras.Sequential([ tf.keras.layers.Dense(10, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(0.01), input_shape=(6,)), tf.keras.layers.Dropout(0.3), tf.keras.layers.Dense(10, activation='relu'), tf.keras.layers.Dense(1) ]) # 编译与训练 model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), loss='mse') model.fit(train_dataset, epochs=100, verbose=0) # 预测测试集并计算MSE y_pred = model.predict(x_test) mse = mean_squared_error(y_test, y_pred) mse_scores.append(mse) print("Mean MSE:", np.mean(mse_scores)) ``` --- ### **关键改进总结** | 原问题 | 修正方案 | |--------|----------| | 未定义`mse`变量 | 使用`sklearn.metrics.mean_squared_error`计算 | | 在训练集上评估 | 改为对测试集(`x_test`)预测 | | 数据管道未优化 | 添加`shuffle`、`batch`和`prefetch` | | 潜在数据泄露 | 每次循环独立进行归一化 | | Dropout/正则化效率低 | 调整参数至合理范围 | 通过以上修正,代码可正确实现留一交叉验证,并准确评估模型性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值