Loading

机器学习实践—鸢尾花数据集

鸢尾花的分类——TensorFlow下的实验

导入和解析数据集

  • 下载数据集

    tf.keras.utils.get_file函数下载训练数据及文件,并返回下载文件的文件路径:

    train_dataset_url = "https://storage.googleapis.com/download.tensorflow.org/data/iris_training.csv"
    #下载路径
    train_dataset_fp = tf.keras.utils.get_file(fname=os.path.basename(train_dataset_url),
                                               origin=train_dataset_url)
    #文件保存路径
    print("本地文件路径: {}".format(train_dataset_fp))
    
  • 检查数据

    !head -n5 {train_dataset_fp}函数提取样本基本信息。

    1. 第一行是表头,有数据集数量,label种类。
    2. 后面几行是样本,含有数据特征信息和一个标签名称。
    120,4,setosa,versicolor,virginica
    6.4,2.8,5.6,2.2,2
    5.0,2.3,3.3,1.0,1
    4.9,2.5,4.5,1.7,2
    4.9,3.1,1.5,0.1,0
    
  • 将数据用python列表存储下来

    根据之前head查看到的数据格式,分别创建feature_name, label_name, class_names列表

    # column order in CSV file
    column_names = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'species']
    #包含feature和label的值
    
    feature_names = column_names[:-1]
    label_name = column_names[:-1]
    
    
  • 创建一个tf.data.Dataset
    1. TF的dataset API可以处理在向模型加载数据时遇到的各种常见情况,是一种高阶API

    2. 由于数据集是CSV文件,我们要通过make_csv_dataset将其变为适合训练模型使用的数据形式

      这里feature字典的意思是说,我们对一个feature来说,这个字典内包含了所有样本的对应该feature的值,这样显然不利于我们构建模型。

      我们要的是对一个样本来说,将它的所有feature按序保存在一个数组里,并且每个样本feature数组与一个label对应。

    """"make_csv_dataset返回一个(features, label)对,
    
    其中features是一个字典:{'feature_name': value}"""
    --->
    train_dataset = tf.data.experimental.make_csv_dataset(
        train_dataset_fp,
        batch_size,
        column_names=column_names,
        label_name=label_name,
        num_epochs=1,
    )
    --->
    print(features)
    print(labels)
    
    --->
    #具有相同特征的样本被分到了同一个字典内,不利于我们构建模型
    OrderedDict([('sepal_length', <tf.Tensor: shape=(32,), dtype=float32, numpy=
    array([5.1, 6.8, 5. , 5.6, 5. , 5.7, 5. , 5.4, 4.9, 5.5, 4.6, 5. , 6.4,
           5. , 6.2, 6.7, 6. , 6.1, 6. , 5.8, 6.3, 7.7, 6.6, 5.1, 4.6, 4.8,
           6.4, 6.4, 5.7, 5.8, 6.8, 5.2], dtype=float32)>), ('sepal_width', <tf.Tensor: shape=(32,), dtype=float32, numpy=
    array([3.8, 3.2, 3.5, 2.5, 3.6, 2.9, 3.4, 3.9, 3. , 2.6, 3.2, 3. , 3.2,
           3.5, 3.4, 3.3, 3. , 2.9, 2.2, 4. , 3.3, 3. , 2.9, 3.8, 3.6, 3. ,
           2.8, 2.7, 4.4, 2.7, 3. , 3.5], dtype=float32)>), ('petal_length', <tf.Tensor: shape=(32,), dtype=float32, numpy=
    array([1.5, 5.9, 1.6, 3.9, 1.4, 4.2, 1.6, 1.3, 1.4, 4.4, 1.4, 1.6, 4.5,
           1.3, 5.4, 5.7, 4.8, 4.7, 5. , 1.2, 6. , 6.1, 4.6, 1.9, 1. , 1.4,
           5.6, 5.3, 1.5, 5.1, 5.5, 1.5], dtype=float32)>), ('petal_width', <tf.Tensor: shape=(32,), dtype=float32, numpy=
    array([0.3, 2.3, 0.6, 1.1, 0.2, 1.3, 0.4, 0.4, 0.2, 1.2, 0.2, 0.2, 1.5,
           0.3, 2.3, 2.1, 1.8, 1.4, 1.5, 0.2, 2.5, 2.3, 1.3, 0.4, 0.2, 0.1,
           2.2, 1.9, 0.4, 1.9, 2.1, 0.2], dtype=float32)>)])
    
    tf.Tensor([0 2 0 1 0 1 0 0 0 1 0 0 1 0 2 2 2 1 2 0 2 2 1 0 0 0 2 2 0 2 2 0], shape=(32,), dtype=int32)
    
    1. 将该feature字典转换格式为(feature, label)形式的数组

      #调用tf.stack方法,从张量列表中获取值,并创建指定维度的组合张量
      --->
      def pack_features_vector(features, labels):
        """Pack the features into a single array."""
        features = tf.stack(list(features.values()), axis=1)
        return features, labels
      --->
      #调用map方法,将每个 (features,label) 对中的 features 打包到训练数据集中:
      --->
      train_dataset = train_dataset.map(pack_features_vector)
      
      features, labels = next(iter(train_dataset))
      
      print(features[0:len(features)])
      --->
      tf.Tensor(
      [[6.7 3.1 4.4 1.4]
       [5.6 2.9 3.6 1.3]
       [6.  2.2 5.  1.5]
       [6.1 3.  4.9 1.8]
       ......
      

      至此我们的解析数据工作完成。

    2. 关于Dataset中的参数batch_size:对于一个有 2000 个训练样本的数据集。将 2000 个样本分成大小为 500 的 batch,那么完成一个 epoch 需要 4 个 iteration

构建模型与训练

  • 模型类型
  1. 使用keras创建模型
  2. 在模型最后一层使用softmax操作子
  • 训练模型构建
    1. 定义损失函数和梯度函数

      #损失函数
      loss_object = tf.keras.losses.XXX
      
      #定义梯度函数从而计算梯度来优化模型
      def grad(model, inputs, targets):
       	with tf.GradientTape() as tape:
       		loss_value = loss(model, inputs, targets, training=True)
      	return loss_value, tape.gradient(loss_value, model.trainable_variables)
      
    2. 创建优化器

      由于神经网络参数数量极大,结构复杂,传统的gradient desent由于要遍历整个数据集,因此不适用于神经网络的额参数学习,相似的有随机梯度下降。

      优化器会将计算出的梯度应用于模型的变量,以使 loss 函数最小化。我们可以用优化器来优化我们的每一步

  • 模型训练循环
    1. 迭代每个周期。通过一次数据集即为一个周期。其中epoch是遍历数据集合的次数。
    2. 在一个周期中,遍历训练 Dataset 中的每个样本,并获取样本的特征(x)和标签(y)
    3. 根据样本的特征进行预测,并比较预测结果和标签。衡量预测结果的不准确性,并使用所得的值计算模型的损失和梯度。
    4. 使用 optimizer 更新模型的变量。
    5. 跟踪一些统计信息以进行可视化。
    6. 对每个周期重复执行以上步骤。
  • 可视化损失函数随时间推移而变化的情况

    TensorBoard 是与 TensorFlow 封装在一起的出色可视化工具,不过我们可以使用 matplotlib 模块创建基本图表。

评估模型的效果

  • 建立测试数据集

    按照与下载训练集相同的方法,将测试集的数据转变为向量形式即可。

  • 根据测试数据集评估模型

    我们会遍历测试集中的每个样本,然后将模型的预测结果与实际标签进行比较。

posted @ 2022-03-25 23:12  王子春  阅读(104)  评论(0编辑  收藏  举报