Pytorch 实践 —— 乳腺癌预测

欢迎关注 “小白玩转Python”,发现更多 “有趣”

1. 数据集

检测乳腺癌一般有30项特征,加载数据集来了解一下这些特征变量:

数据的尺寸

变量及其类型

在检查重复数据和空数据并确认数据集不受此限制之后,是时候检查不必要的数据了。从数据集的33列中,id 和 Unnamed:32 被删除了:

df.drop(['id','Unnamed: 32'],axis=1,inplace=True)

完成第一部分,用 .describe() 函数来了解统计学:

2. 可视化

检查良恶性肿瘤的数量:

有357例良性肿瘤诊断和212例恶性肿瘤诊断,这似乎是一个相当平衡的数据集。

现在可视化其他变量的分布:

每个变量的分布

变量之间的相关性

从上面的数据情况我们可以得到以下的结论:

  • 这是一个相当复杂的模型,能够可视化的相关性

  • 肿瘤平均半径为14.12,最小为6.98,最大为28.11

  • 维度相关的变量是正相关的(例如 area_se 和 perimeter_se)

  • 数据集中62.7% 的肿瘤是良性的,37.3% 是恶性的

3. 为机器学习准备数据

更换标签

我们想要预测的数值在“diagnosis”一栏中ーー这些是标签。我们想预测一个肿瘤是恶性的(M)还是良性的(B)。数据框架中的所有其他列都是模型的预测变量:

标签由字母 M(恶性)和 B(良性)表示。第一步是将这些信息转换成数值型的数据,良性的数据为0,恶性的数据为1:

lab ={'B':0,'M':1}
df = df.replace({'diagnosis':lab})
df.head()

现在,数据可以分为两个部分:

预测变量:我们将提供的数据作为模型的输入,以作出预测

predictors = df.iloc[:, 2:31]
predictors

标签:我们要预测的信息,即根据预测数据集中的信息,预测该肿瘤是恶性的还是良性的

labels = df.iloc[:, 0:1]
labels

转换为张量,并将数据分割为训练和测试子集

使用 scikit learn 库,使用20% 的比例将数据集分成训练和测试数据:

predictors_train, predictors_test, labels_train, labels_test = train_test_split(predictors,labels,test_size = 0.20)

到目前为止,这些数据都存储在 pandas 的数据帧中。由于我们将使用张量流来实现深度学习模型,因此必须将数据转换为张量。首先,将 pandas 数据帧转换为数组:

type(np.array(predictors_train))

Out[20]:

type(np.array(labels_train))

Out[21]:

numpy.ndarray

该模型将使用 PyTorch 实现,因此下一步是将该数组转换为一个 torch 元素:

predictors_train = torch.tensor(np.array(predictors_train), dtype=torch.float)


labels_train = torch.tensor(np.array(labels_train), dtype = torch.float)


df_tf = torch.utils.data.TensorDataset(predictors_train, labels_train)
type(df_tf)

Pytorch 对模型进行了小批量的训练。有一个名为 DataLoader 的类用于在数据集上执行迭代。批量大小参数给出了在调整模型权重时考虑的样本数:

train_loader = torch.utils.data.DataLoader(df_tf, batch_size=15, shuffle=True)

4. 模型的实现与评估

在本项目中,将实现一个具有两个隐藏层的神经网络。要实现这个模型,我们需要:

  • 定义模型的结构(定义层数,神经元,激活函数)

  • 选择一个训练策略

  • 选择一个优化器

由于问题的复杂性和未知性,这种类型的实现被建模为一个最佳化问题。因此,选择一个优化器是整个过程的一部分。

在最佳化问题中,我们有目标函数(称为成本函数或损失函数)。这就是我们要优化的函数。在神经网络的目标是最小化的误差,因此最小化的损失(或成本)函数。

构建模型

神经网络模型的定义如下:

classifier = nn.Sequential(
  
    nn.Linear(in_features=29, out_features=15),
    nn.ReLU(),
    nn.Linear(15, 15),
    nn.ReLU(),
    nn.Linear(15, 1),
    nn.Sigmoid()
)
  • Input features = 29(我们在预测数据集中有29个特性)

  • 2个隐藏层,每层有15个神经元

  • 输出层有一个神经元,输出标记0(良性肿瘤)和1(恶性肿瘤)

  • ReLu:内部层的非线性激活函数

  • Sigmoid:输出层的非线性激活函数,返回的概率介于0和1之间

ReLu 是一种非线性激活函数,它的优点是不会同时激活所有的神经元。ReLu 被选中做第一次尝试,以建立更有效的计算成本方面的模型。

据报道,Sigmoid 在分类问题上效果很好。因为我们有一个输出层分类肿瘤良性或恶性,Sigmoid 被选为激活函数。

训练策略

现在,我们必须选择神经网络的训练策略。由于这是一个二元分类任务,选择二元交叉熵准则是:

criterion = nn.BCELoss()

优化器

第三步,也是最后一步:选择优化器。Adam 优化算法是深度学习问题中一种非常流行的选择算法。这是随机梯度下降算法的扩展,但与 SGD 算法不同,Adam 优化器在训练期间并不保持相同的学习速率。

optimizer = torch.optim.Adam(classifier.parameters(), lr=0.001, weight_decay=0.0001)

训练模型

更新后的权重将运行100次,如下面的 for 循环所示:

for epoch in range(100):
  #To store the error:
  run_loss = 0.


  for data in train_loader:
    inputs, labels = data
    optimizer.zero_grad()


    outputs = classifier(inputs)     error = criterion(outputs, labels)
    error.backward()
    optimizer.step() 


    run_loss += error.item()
  print('Epoch %3d: loss %.5f' % (epoch+1, run_loss/len(train_loader)))
  • 训练数据加载器将训练数据分批加载(这个模型选择的批量大小是15个样本)

  • zero_grad() 在反向传播过程之前,将梯度设置为零

  • outputs 计算对模型的预测

  • error 计算出计算中的误差,并将预测结果与实际数据进行比较

  • error.backward() 是神经网络中的反向传播过程来更新权值

  • optimizer.step() 更新权重

评估模型

这个模型的准确率达到了94.73% ,在我们的混淆矩阵中可以看到这一点:

分类器总共做出了114个预测,从中可以看出:

  • 70例标本被正确估计为良性肿瘤

  • 38例标本正确诊断为恶性肿瘤

  • 有3个样本被估计为假阴性,这些应该被分类为恶性肿瘤,但被分类为良性

  • 3个样本被估计为假阳性

·  END  ·

HAPPY LIFE

  • 4
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值