为新数据集开发神经网络预测模型可能具有挑战性。

一种方法是首先检查数据集并就哪些模型可能起作用提出想法,然后探索数据集上简单模型的学习动态,最后使用强大的测试工具为数据集开发和调整模型。

此过程可用于为分类和回归预测建模问题开发有效的神经网络模型。

在本教程中,您将了解如何为癌症生存二元分类数据集开发多层感知器神经网络模型。

完成本教程后,您将了解:

  • 如何加载和总结癌症生存数据集并使用结果来建议要使用的数据准备和模型配置。
  • 如何探索简单 MLP 模型在数据集上的学习动态。
  • 如何对模型性能进行稳健的估计、调整模型性能并对新数据进行预测。

让我们开始吧。

教程概述

本教程分为4部分;他们是:

  1. Haberman 乳腺癌生存数据集
  2. 神经网络学习动力学
  3. 稳健的模型评估
  4. 最终模型并进行预测

Haberman 乳腺癌生存数据集

第一步是定义和探索数据集。

我们将使用“ haberman ”标准二元分类数据集。

该数据集描述了乳腺癌患者数据,结果是患者存活率。特别是患者是否存活了五年或更长时间,或者患者是否没有存活下来。

这是用于研究不平衡分类的标准数据集。根据数据集描述,这些手术是在 1958 年至 1970 年间在芝加哥大学比林斯医院进行的。

数据集中有306个例子,输入变量有3个;他们是:

  • 手术时患者的年龄。
  • 操作的两位数年份。
  • 检测到的“阳性腋窝淋巴结”数量,衡量癌症是否已经扩散。

因此,除了数据集中可用的内容之外,我们无法控制构成数据集的案例的选择或在这些案例中使用的特征。

尽管该数据集描述了乳腺癌患者的存活率,但鉴于数据集规模较小,而且数据是基于几十年前的乳腺癌诊断和操作这一事实,因此基于该数据集构建的任何模型预计都不会泛化。

注意:明确地说,我们不是“解决乳腺癌”。我们正在探索一个标准的分类数据集。

下面是数据集前 5 行的示例


30,64,1,1

30,62,3,1

30,65,0,1

31,59,2,1

31,65,4,1

...

您可以在此处了解有关数据集的更多信息:

  • 哈伯曼生存数据集 (haberman.csv)
  • Haberman 生存数据集详细信息 (haberman.names)

我们可以直接从 URL 加载数据集作为 Pandas DataFrame;例如:

    # load the haberman dataset and summarize the shape

    from pandas import read_csv

    # define the location of the dataset

    url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/haberman.csv'

    # load the dataset

    df = read_csv(url, header=None)

    # summarize shape

    print(df.shape)

    运行示例直接从 URL 加载数据集并报告数据集的形状。

    在这种情况下,我们可以确认数据集有 4 个变量(3 个输入和 1 个输出)并且数据集有 306 行数据。

    对于神经网络而言,这并不是很多数据行,这表明可能具有正则化的小型网络将是合适的。

    它还表明,使用 k 折交叉验证将是一个好主意,因为它可以提供比训练/测试拆分更可靠的模型性能估计,并且因为单个模型将在几秒钟内拟合,而不是几小时或几天最大的数据集。

    接下来,我们可以通过查看汇总统计数据和数据图来了解有关数据集的更多信息。

      # show summary statistics and plots of the haberman dataset

      from pandas import read_csv

      from matplotlib import pyplot

      # load the dataset

      df = read_csv(url, header=None)

      # show summary statistics

      print(df.describe())

      # plot histograms

      df.hist()

      pyplot.show()

      运行示例首先加载之前的数据,然后输出每个变量的汇总统计信息。

      我们可以看到值随均值和标准差的不同而变化,在建模之前可能需要进行一些归一化或标准化。

          0           1           2           3

        count 306.000000 306.000000 306.000000 306.000000

        mean 52.457516 62.852941 4.026144 1.264706

        std 10.803452 3.249405 7.189654 0.441899

        min 30.000000 58.000000 0.000000 1.000000

        25% 44.000000 60.000000 0.000000 1.000000

        50% 52.000000 63.000000 1.000000 1.000000

        75% 60.750000 65.750000 4.000000 2.000000

        max 83.000000 69.000000 52.000000 2.000000

        然后为每个变量创建直方图。

        我们可以看到,第一个变量可能具有类高斯分布,接下来的两个输入变量可能具有指数分布。

        我们在每个变量上使用幂变换可能会有一些好处,以使概率分布不那么偏斜,这可能会提高模型性能。


        Keras为癌症生存数据集开发神经网络_Keras


        Haberman 乳腺癌生存分类数据集的直方图

        我们可以看到两个类之间的示例分布有些偏差,这意味着分类问题不平衡。它是不平衡的。

        了解数据集的实际不平衡程度可能会有所帮助。

        我们可以使用 Counter 对象来计算每个类中示例的数量,然后使用这些计数来总结分布。

        下面列出了完整的示例。

          # summarize the class ratio of the haberman dataset

          from pandas import read_csv

          from collections import Counter

          # define the dataset column names

          columns = ['age', 'year', 'nodes', 'class']

          # load the csv file as a data frame

          dataframe = read_csv(url, header=None, names=columns)

          # summarize the class distribution

          target = dataframe['class'].values

          counter = Counter(target)

          for k,v in counter.items():

          per = v / len(target) * 100

          print('Class=%d, Count=%d, Percentage=%.3f%%' % (k, v, per))

          运行示例总结了数据集的类分布。

          我们可以看到,生存类 1 的样本最多,为 225,约占数据集的 74%。我们可以看到非生存类 2 在 81 处的示例较少,约占数据集的 26%。

          类分布偏斜,但没有严重失衡。

            Class=1, Count=225, Percentage=73.529%

            Class=2, Count=81, Percentage=26.471%

            这很有帮助,因为如果我们使用分类准确率,那么任何达到低于约 73.5% 准确率的模型都不具备该数据集的技能。

            现在我们熟悉了数据集,让我们探索如何开发神经网络模型。

            神经网络学习动力学

            我们将使用TensorFlow为数据集开发多层感知器 (MLP) 模型。

            我们不知道学习超参数的模型架构对这个数据集是好的还是最好的,所以我们必须试验并发现什么是有效的。

            鉴于数据集很小,小批量可能是一个好主意,例如 16 或 32 行。开始时使用 Adam 版本的随机梯度下降是一个好主意,因为它会自动调整学习率并且在大多数数据集上运行良好。

            在我们认真评估模型之前,最好先回顾学习动态并调整模型架构和学习配置,直到我们拥有稳定的学习动态,然后再考虑充分利用模型。

            我们可以通过使用简单的数据训练/测试分割和学习曲线图来做到这一点。这将帮助我们了解我们是过度学习还是学习不足;然后我们可以相应地调整配置。

            首先,我们必须确保所有输入变量都是浮点值,并将目标标签编码为整数值 0 和 1。

              # ensure all data are floating point values

              X = X.astype('float32')

              # encode strings to integer

              y = LabelEncoder().fit_transform(y)

              接下来,我们可以将数据集拆分为输入和输出变量,然后拆分为 67/33 的训练集和测试集。

              我们必须确保分割按类别分层,确保训练集和测试集具有与主数据集相同的类别标签分布。

                ...

                # split into input and output columns

                X, y = df.values[:, :-1], df.values[:, -1]

                # split into train and test datasets

                X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, stratify=y, random_state=3)

                我们可以定义一个最小的 MLP 模型。在这种情况下,我们将使用一个具有 10 个节点的隐藏层和一个输出层(任意选择)。我们将使用隐藏层中的ReLU 激活函数和“ he_normal ”权重初始化,它们一起是一个很好的做法。

                模型的输出是用于二元分类的 sigmoid 激活,我们将最小化二元交叉熵损失。

                  ...

                  # determine the number of input features

                  n_features = X.shape[1]

                  # define model

                  model = Sequential()

                  model.add(Dense(10, activation='relu', kernel_initializer='he_normal', input_shape=(n_features,)))

                  model.add(Dense(1, activation='sigmoid'))

                  # compile the model

                  model.compile(optimizer='adam', loss='binary_crossentropy')

                  我们将模型拟合 200 个训练时期(任意选择),批量大小为 16,因为它是一个小数据集。

                  我们正在根据原始数据拟合模型,我们认为这可能是个好主意,但这是一个重要的起点。

                    ...

                    # fit the model

                    history = model.fit(X_train, y_train, epochs=200, batch_size=16, verbose=0, validation_data=(X_test,y_test))

                    在训练结束时,我们将评估模型在测试数据集上的性能,并将性能报告为分类准确率。

                      ..

                      # predict test set

                      yhat = model.predict_classes(X_test)

                      # evaluate predictions

                      score = accuracy_score(y_test, yhat)

                      print('Accuracy: %.3f' % score)

                      最后,我们将在训练期间绘制训练集和测试集上交叉熵损失的学习曲线。

                        ..

                        # plot learning curves

                        pyplot.title('Learning Curves')

                        pyplot.xlabel('Epoch')

                        pyplot.ylabel('Cross Entropy')

                        pyplot.plot(history.history['loss'], label='train')

                        pyplot.plot(history.history['val_loss'], label='val')

                        pyplot.legend()

                        pyplot.show()

                        将所有这些结合在一起,下面列出了在癌症生存数据集上评估我们的第一个 MLP 的完整示例。

                          # fit a simple mlp model on the haberman and review learning curves

                          from pandas import read_csv

                          from sklearn.model_selection import train_test_split

                          from sklearn.preprocessing import LabelEncoder

                          from sklearn.metrics import accuracy_score

                          from tensorflow.keras import Sequential

                          from tensorflow.keras.layers import Dense

                          from matplotlib import pyplot

                          df = read_csv(path, header=None)

                          # split into input and output columns

                          X, y = df.values[:, :-1], df.values[:, -1]

                          # ensure all data are floating point values

                          X = X.astype('float32')

                          # encode strings to integer

                          y = LabelEncoder().fit_transform(y)

                          # split into train and test datasets

                          X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, stratify=y, random_state=3)

                          # determine the number of input features

                          n_features = X.shape[1]

                          # define model

                          model = Sequential()

                          model.add(Dense(10, activation='relu', kernel_initializer='he_normal', input_shape=(n_features,)))

                          model.add(Dense(1, activation='sigmoid'))

                          # compile the model

                          model.compile(optimizer='adam', loss='binary_crossentropy')

                          # fit the model

                          history = model.fit(X_train, y_train, epochs=200, batch_size=16, verbose=0, validation_data=(X_test,y_test))

                          # predict test set

                          yhat = model.predict_classes(X_test)

                          # evaluate predictions

                          score = accuracy_score(y_test, yhat)

                          print('Accuracy: %.3f' % score)

                          # plot learning curves

                          pyplot.title('Learning Curves')

                          pyplot.xlabel('Epoch')

                          pyplot.ylabel('Cross Entropy')

                          pyplot.plot(history.history['loss'], label='train')

                          pyplot.plot(history.history['val_loss'], label='val')

                          pyplot.legend()

                          pyplot.show()

                          运行示例首先在训练数据集上拟合模型,然后在测试数据集上报告分类准确率。

                          在这种情况下,我们可以看到该模型的性能优于非技能模型,因为准确度高于约 73.5%。

                          然后创建训练集和测试集上的损失线图。

                          我们可以看到模型很快在数据集上找到了很好的拟合,并且没有出现过拟合或欠拟合的情况。


                          Keras为癌症生存数据集开发神经网络_癌症_02


                          简单多层感知器在癌症生存数据集上的学习曲线

                          现在我们对数据集上的简单 MLP 模型的学习动态有了一些了解,我们可以考虑对数据集上的模型性能进行更稳健的评估。

                          稳健的模型评估

                          k 折交叉验证过程可以提供更可靠的 MLP 性能估计,尽管它可能非常慢。

                          这是因为必须拟合和评估 k 个模型。当数据集规模较小时,这不是问题,例如癌症生存数据集。

                          我们可以使用StratifiedKFold类并手动枚举每个折叠,拟合模型,评估它,然后在程序结束时报告评估分数的平均值。

                            ...

                            # prepare cross validation

                            kfold = KFold(10)

                            # enumerate splits

                            scores = list()

                            for train_ix, test_ix in kfold.split(X, y):

                            # fit and evaluate the model...

                            ...

                            ...

                            # summarize all scores

                            print('Mean Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

                            我们可以使用这个框架,通过我们的基本配置,甚至使用一系列不同的数据准备、模型架构和学习配置,对 MLP 模型性能进行可靠的估计。

                            重要的是,在使用 k 折交叉验证来估计性能之前,我们首先了解了上一节中模型在数据集上的学习动态。如果我们直接开始调整模型,我们可能会得到很好的结果,但如果不是,我们可能不知道为什么,例如模型过度拟合或拟合不足。

                            如果我们再次对模型进行大量更改,最好返回并确认模型是否正确收敛。

                            下面列出了该框架的完整示例,用于评估上一节中的基本 MLP 模型。

                              # k-fold cross-validation of base model for the haberman dataset

                              from numpy import mean

                              from numpy import std

                              from pandas import read_csv

                              from sklearn.model_selection import StratifiedKFold

                              from sklearn.preprocessing import LabelEncoder

                              from sklearn.metrics import accuracy_score

                              from tensorflow.keras import Sequential

                              from tensorflow.keras.layers import Dense

                              from matplotlib import pyplot

                              # load the dataset

                              path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/haberman.csv'

                              df = read_csv(path, header=None)

                              # split into input and output columns

                              X, y = df.values[:, :-1], df.values[:, -1]

                              # ensure all data are floating point values

                              X = X.astype('float32')

                              # encode strings to integer

                              y = LabelEncoder().fit_transform(y)

                              # prepare cross validation

                              kfold = StratifiedKFold(10, random_state=1)

                              # enumerate splits

                              scores = list()

                              for train_ix, test_ix in kfold.split(X, y):

                              # split data

                              X_train, X_test, y_train, y_test = X[train_ix], X[test_ix], y[train_ix], y[test_ix]

                              # determine the number of input features

                              n_features = X.shape[1]

                              # define model

                              model = Sequential()

                              model.add(Dense(10, activation='relu', kernel_initializer='he_normal', input_shape=(n_features,)))

                              model.add(Dense(1, activation='sigmoid'))

                              # compile the model

                              model.compile(optimizer='adam', loss='binary_crossentropy')

                              # fit the model

                              model.fit(X_train, y_train, epochs=200, batch_size=16, verbose=0)

                              # predict test set

                              yhat = model.predict_classes(X_test)

                              # evaluate predictions

                              score = accuracy_score(y_test, yhat)

                              print('>%.3f' % score)

                              scores.append(score)

                              # summarize all scores

                              print('Mean Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

                              运行示例报告评估程序的每次迭代的模型性能,并报告运行结束时分类准确度的均值和标准差。

                              在这种情况下,我们可以看到 MLP 模型实现了大约 75.2% 的平均准确率,这与我们在上一节中的粗略估计非常接近。

                              这证实了我们的预期,即基本模型配置可能比此数据集的朴素模型更有效

                                >0.742

                                >0.774

                                >0.774

                                >0.806

                                >0.742

                                >0.710

                                >0.767

                                >0.800

                                >0.767

                                >0.633

                                Mean Accuracy: 0.752 (0.048)

                                这是一个好结果吗?

                                事实上,这是一个具有挑战性的分类问题,达到 74.5% 以上的分数是好的。

                                接下来,让我们看看如何拟合最终模型并使用它进行预测。

                                最终模型并进行预测

                                一旦我们选择了模型配置,我们就可以在所有可用数据上训练最终模型,并使用它对新数据进行预测。

                                在这种情况下,我们将使用带有 dropout 和小批量的模型作为我们的最终模型。

                                我们可以像以前一样准备数据并拟合模型,尽管是在整个数据集而不是数据集的训练子集上。

                                  ...

                                  # split into input and output columns

                                  X, y = df.values[:, :-1], df.values[:, -1]

                                  # ensure all data are floating point values

                                  X = X.astype('float32')

                                  # encode strings to integer

                                  le = LabelEncoder()

                                  y = le.fit_transform(y)

                                  # determine the number of input features

                                  n_features = X.shape[1]

                                  # define model

                                  model = Sequential()

                                  model.add(Dense(10, activation='relu', kernel_initializer='he_normal', input_shape=(n_features,)))

                                  model.add(Dense(1, activation='sigmoid'))

                                  # compile the model

                                  model.compile(optimizer='adam', loss='binary_crossentropy')

                                  然后我们可以使用这个模型对新数据进行预测。

                                  首先,我们可以定义一行新数据。

                                    ...

                                    # define a row of new data

                                    row = [30,64,1]

                                    注意:我从数据集的第一行中取出这一行,预期的标签是“1”。

                                    然后我们可以进行预测。

                                      ...

                                      # make prediction

                                      yhat = model.predict_classes([row])

                                      然后反转预测的变换,这样我们就可以在正确的标签中使用或解释结果(这只是这个数据集的一个整数)。

                                        ...

                                        # invert transform to get label for class

                                        yhat = le.inverse_transform(yhat)

                                        在这种情况下,我们将简单地报告预测。

                                          ...

                                          # report prediction

                                          print('Predicted: %s' % (yhat[0]))

                                          将所有这些结合在一起,下面列出了为 haberman 数据集拟合最终模型并使用它对新数据进行预测的完整示例。

                                            # fit a final model and make predictions on new data for the haberman dataset

                                            from pandas import read_csv

                                            from sklearn.preprocessing import LabelEncoder

                                            from sklearn.metrics import accuracy_score

                                            from tensorflow.keras import Sequential

                                            from tensorflow.keras.layers import Dense

                                            from tensorflow.keras.layers import Dropout

                                            df = read_csv(path, header=None)

                                            # split into input and output columns

                                            X, y = df.values[:, :-1], df.values[:, -1]

                                            # ensure all data are floating point values

                                            X = X.astype('float32')

                                            # encode strings to integer

                                            le = LabelEncoder()

                                            y = le.fit_transform(y)

                                            # determine the number of input features

                                            n_features = X.shape[1]

                                            # define model

                                            model = Sequential()

                                            model.add(Dense(10, activation='relu', kernel_initializer='he_normal', input_shape=(n_features,)))

                                            model.add(Dense(1, activation='sigmoid'))

                                            # compile the model

                                            model.compile(optimizer='adam', loss='binary_crossentropy')

                                            # fit the model

                                            model.fit(X, y, epochs=200, batch_size=16, verbose=0)

                                            # define a row of new data

                                            row = [30,64,1]

                                            # make prediction

                                            yhat = model.predict_classes([row])

                                            # invert transform to get label for class

                                            yhat = le.inverse_transform(yhat)

                                            # report prediction

                                            print('Predicted: %s' % (yhat[0]))

                                            运行示例在整个数据集上拟合模型,并对单行新数据进行预测。

                                            在这种情况下,我们可以看到模型预测了输入行的“1”标签。


                                            概括

                                            在本文中,您了解了如何为癌症生存二元分类数据集开发多层感知器神经网络模型。

                                            具体来学到了:

                                            • 如何加载和总结癌症生存数据集并使用结果来建议要使用的数据准备和模型配置。
                                            • 如何探索简单 MLP 模型在数据集上的学习动态。
                                            • 如何对模型性能进行稳健的估计、调整模型性能并对新数据进行预测。


                                            欢迎各位同学了解<python机器学习生物信息学>课程,系统化学习机器学习建模知识

                                            ​https://edu.51cto.com/topic/4283.html​

                                            版权声明:文章来自公众号(python风控模型),未经许可,不得抄袭。遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。