机器学习13: 使用 TensorFlow 进行二元分类(Binary Classification)编程实践

news2024/11/18 3:00:12

在【机器学习6】和【机器学习9】中,我们使用 TensorFlow 进行了“线性回归模型”和“组合特征”编程实践。本质上,其中采用的都是回归模型,也就是说,我们创建了产生浮点预测的模型,比如“这个社区的房子要花 N 千美元。” 在本篇,我们将创建并评估一个二进制分类模型。

学习目标:

  • 将回归问题转换为分类问题。
  • 修改分类阈值并确定该修改对模型有什么影响。
  • 尝试使用不同的分类指标来确定模型的有效性。

数据集:与【机器学习9】一样,编程练习中也使用加州住房数据集。

目录

1.导入依赖模块

2.载入数据集

3.数据归一化(Normalize values)

4.创建二进制标签

5.将特征表示为输入图层

6.定义构建和训练模型的函数

7.定义打印函数

8.调用创建、训练和绘图函数

9.任务一

10.任务二:添加精确度和召回率作为衡量标准

11.任务三:试验分类阈值

12.任务四:总结模型性能(如果时间允许)

13.参考文献


1.导入依赖模块

import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow.keras import layers
from matplotlib import pyplot as plt

# The following lines adjust the granularity of reporting.
pd.options.display.max_rows = 10
pd.options.display.float_format = "{:.1f}".format
# tf.keras.backend.set_floatx('float32')

print("Ran the import statements.")

2.载入数据集

本案例中采用的数据集原始地址为如下:

  • 训练数据:https://download.mlcc.google.com/mledu-datasets/california_housing_train.csv
  • 测试数据:https://download.mlcc.google.com/mledu-datasets/california_housing_test.csv

我们需要将上述数据下载到本地,然后将其路径(数据文件在你电脑的实际路径)写入代码中,如下代码所示:

# 载入数据集
train_df = pd.read_csv("/Users/shulan/Downloads/california_housing_train.csv")
test_df = pd.read_csv("/Users/shulan/Downloads/california_housing_test.csv")
# 打乱训练数据示例
train_df = train_df.reindex(np.random.permutation(train_df.index))

3.数据归一化(Normalize values)

当创建具有多个特征的模型时,每个特征的值应该覆盖大致相同的范围。例如,如果一个特征的范围从 500 到 100000,而另一个特征范围从 2 到 12,那么模型将很难或不可能训练。因此,在训练之前,需要将特征数据进行规范化(归一化)处理。

以下代码单元通过将每个原始值(包括标签)转换为其 Z 分数来规范数据集。Z 分数是特定原始值与平均值之间的标准偏差数。假设数据集满足如下要求:

  • 平均值为 60。
  • 标准偏差为 10。

那么,原始值 75 的 Z 分数为 +1.5:Z分数=(75-60)/10=+1.5。原始值 38 的 Z 分数为 -2.2:Z分数=(38-60)/10=-2.2。经过上述处理,我们就实现了对数据的归一化处理。

# 计算训练集中每列的Z分数,并将这些Z分数写入名为 train_df_norm 的新 Panda DataFrame 中。
train_df_mean = train_df.mean()
train_df_std = train_df.std()
train_df_norm = (train_df - train_df_mean) / train_df_std

# 检查规范化训练集的一些值。请注意,大多数Z分数都在-2和+2之间。
train_df_norm.head()

# 计算测试集中每列的Z分数,并将这些Z分数写入名为 test_df_norm 的新 Panda DataFrame 中。
test_df_mean = test_df.mean()
test_df_std = test_df.std()
test_df_norm = (test_df - test_df_mean) / test_df_std

4.创建二进制标签

在分类问题中,每个示例的标签必须是 0 或 1。不幸的是,加州住房数据集中的自然标签median_house_value(房价平均值) 包含 80100 或 85700 等浮点值,而不是 0 和 1,而median_house_value 的归一化处理结果属于 -3 和 +3 之间的浮点值。

因此,我们需要在训练集和测试集中创建一个名为 median_house_value_is_high 的新列。如果median_house_value 高于某个任意值(由阈值定义),则将 median_house_value_is_high 设置为 1。否则,将 median_house_value_is_high 设置为 0。

提示:median_house_value_is_high 列中的单元格必须分别包含 1 和 0,而不是 True 和 False。要将 True 和 False 转换为 1 和 0,可调用 pandas DataFrame 函数 astype(float)。

# 根据加州房价平均值,这里将阈值设置为 265000(房价平均值*75%)。房价中值超过 265000 的每个社区都将被标记为 1,所有其他社区都将标记为 0
threshold = 265000
train_df_norm["median_house_value_is_high"] = (train_df["median_house_value"] > threshold).astype(float)
test_df_norm["median_house_value_is_high"] = (test_df["median_house_value"] > threshold).astype(float)
train_df_norm["median_house_value_is_high"].head(8000)

# 除了上面的方法,我们还可以使用Z分数,而不是根据原始房屋值来选择阈值。
# 例如,以下解决方案使用 +1.0 的 Z 分数作为阈值,这意味着 median_house_value_is_high 中不超过 16% 的值将被标记为 1。
# threshold_in_Z = 1.0
# train_df_norm["median_house_value_is_high"] = (train_df_norm["median_house_value"] > threshold_in_Z).astype(float)
# test_df_norm["median_house_value_is_high"] = (test_df_norm["median_house_value"] > threshold_in_Z).astype(float)

5.将特征表示为输入图层

如下代码单元指定了最终训练模型所用的输入特征: median_income 和 total_rooms。这些 Input对象被实例化为 Keras 张量。

inputs = {
# Features used to train the model on.
  'median_income': tf.keras.Input(shape=(1,)),
  'total_rooms': tf.keras.Input(shape=(1,))
}

6.定义构建和训练模型的函数

以下代码单元中,定义了两个函数:

  • create_model(...),它定义了模型的拓扑结构。
  • train_model(...),使用输入特征和标签来训练模型。

先前的练习使用 ReLU 作为激活函数。相比之下,这个练习使用 sigmoid 作为激活函数。

# 定义模型创建函数
def create_model(my_inputs, my_learning_rate, METRICS):
    # 使用连接层将输入层连接到单个张量中。作为致密层的输入。例如:[input_1[0][0],input_2[0][0]
    concatenated_inputs = tf.keras.layers.Concatenate()(my_inputs.values())
    dense = layers.Dense(units=1, input_shape=(1,), name='dense_layer', activation=tf.sigmoid)
    dense_output = dense(concatenated_inputs)
    """创建并编译一个简单的分类模型."""
    my_outputs = {
        'dense': dense_output,
    }
    model = tf.keras.Model(inputs=my_inputs, outputs=my_outputs)

    # 调用compile方法将层构造为TensorFlow可以执行的模型。注意,这里使用的损失函数(sigmoid)与在回归中使用的(ReLU)不同。
    model.compile(optimizer=tf.keras.optimizers.experimental.RMSprop(learning_rate=my_learning_rate),
                  loss=tf.keras.losses.BinaryCrossentropy(),
                  metrics=METRICS)
    return model


# 定义模型训练函数
def train_model(model, dataset, epochs, label_name,
                batch_size=None, shuffle=True):
    """将数据集输入到模型中以便对其进行训练."""

    # tf.keras.Model.fit的x参数可以是数组列表,其中每个数组包含一个特征的数据。
    # 在这里,我们传递数据集中的每一列。注意,feature_layer将过滤掉这些列中的大部分,只留下所需的列及其表示形式作为特征。
    features = {name: np.array(value) for name, value in dataset.items()}
    label = np.array(features.pop(label_name))
    history = model.fit(x=features, y=label, batch_size=batch_size,
                        epochs=epochs, shuffle=shuffle)

    # 将轮次列表与历史的其余部分分开存储
    epochs = history.epoch

    # 隔离每个轮次的分类结果
    hist = pd.DataFrame(history.history)

    return epochs, hist

7.定义打印函数

为了便于评估模型效果,我们需要将训练+测试结果可视化。在下面的代码单元中,使用 matplotlib 函数绘制了一条或多条曲线,显示了各种分类指标如何随每个轮次而变化。

# 定义打印函数
def plot_curve(epochs, hist, list_of_metrics):
    """绘制一个或多个分类度量相对于训练轮次的曲线"""

    plt.figure()
    plt.xlabel("Epoch")
    plt.ylabel("Value")

    for m in list_of_metrics:
        x = hist[m]
        plt.plot(epochs[1:], x[1:], label=m)

    plt.legend()


print("Defined the plot_curve function.")

8.调用创建、训练和绘图函数

以下代码单元调用指定超参数,然后调用函数来创建和训练模型,然后绘制结果。

# 指定超参数
learning_rate = 0.001
epochs = 20
batch_size = 100
label_name = "median_house_value_is_high"
classification_threshold = 0.35

# 建立模型将衡量的指标
METRICS = [
    tf.keras.metrics.BinaryAccuracy(name='accuracy',
                                    threshold=classification_threshold),
]

# 建立模型的拓扑
my_model = create_model(inputs, learning_rate, METRICS)
# 基于训练数据训练模型
epochs, hist = train_model(my_model, train_df_norm, epochs,
                           label_name, batch_size)

# 绘制模型准确度指标和训练轮次的关系图
list_of_metrics_to_plot = ['accuracy']

plot_curve(epochs, hist, list_of_metrics_to_plot)

9.任务一

将上面的代码汇总在一起,运行代码,结果如下:从中可以看出,随着训练轮次的增加,模型的准确度(Accuracy)越来越高。关于准确度的定义,在【机器学习12】中有介绍,这里简单回顾一下——对于二元分类,准确率也可以按照正数和负数来计算,如下所示:

\text{Accuracy} = \frac{TP+TN}{TP+TN+FP+FN}

其中TP = 真阳性,TN = 真阴性,FP = 假阳性,FN = 假阴性。

10.任务二:添加精确度和召回率作为衡量标准

仅仅依靠准确度,尤其是对于类别不平衡的数据集(如我们的数据集),可能无法很好的进行分类。修改上述代码单元中的代码,使模型不仅可以测量准确性,还可以测量精度和召回率。我们增加了准确性和精确性。完整代码如下:

# @title Load the imports

import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow.keras import layers
from matplotlib import pyplot as plt

# The following lines adjust the granularity of reporting.
pd.options.display.max_rows = 10
pd.options.display.float_format = "{:.1f}".format
# tf.keras.backend.set_floatx('float32')

print("Ran the import statements.")

# 载入数据集
train_df = pd.read_csv("/Users/shulan/Downloads/california_housing_train.csv")
test_df = pd.read_csv("/Users/shulan/Downloads/california_housing_test.csv")
# 打乱训练数据示例
train_df = train_df.reindex(np.random.permutation(train_df.index))

# 计算训练集中每列的Z分数,并将这些Z分数写入名为 train_df_norm 的新 Panda DataFrame 中。
train_df_mean = train_df.mean()
train_df_std = train_df.std()
train_df_norm = (train_df - train_df_mean) / train_df_std

# 检查规范化训练集的一些值。请注意,大多数Z分数都在-2和+2之间。
train_df_norm.head()

# 计算测试集中每列的Z分数,并将这些Z分数写入名为 test_df_norm 的新 Panda DataFrame 中。
test_df_mean = test_df.mean()
test_df_std = test_df.std()
test_df_norm = (test_df - test_df_mean) / test_df_std

# 根据加州房价平均值,这里将阈值设置为 265000(房价平均值*75%)。房价中值超过 265000 的每个社区都将被标记为 1,所有其他社区都将标记为 0
threshold = 265000
train_df_norm["median_house_value_is_high"] = (train_df["median_house_value"] > threshold).astype(float)
test_df_norm["median_house_value_is_high"] = (test_df["median_house_value"] > threshold).astype(float)
train_df_norm["median_house_value_is_high"].head(8000)

# 除了上面的方法,我们还可以使用Z分数,而不是根据原始房屋值来选择阈值。
# 例如,以下解决方案使用 +1.0 的 Z 分数作为阈值,这意味着 median_house_value_is_high 中不超过 16% 的值将被标记为 1。
# threshold_in_Z = 1.0
# train_df_norm["median_house_value_is_high"] = (train_df_norm["median_house_value"] > threshold_in_Z).astype(float)
# test_df_norm["median_house_value_is_high"] = (test_df_norm["median_house_value"] > threshold_in_Z).astype(float)

inputs = {
    # Features used to train the model on.
    'median_income': tf.keras.Input(shape=(1,)),
    'total_rooms': tf.keras.Input(shape=(1,))
}


# 定义模型创建函数
def create_model(my_inputs, my_learning_rate, METRICS):
    # 使用连接层将输入层连接到单个张量中。作为致密层的输入。例如:[input_1[0][0],input_2[0][0]
    concatenated_inputs = tf.keras.layers.Concatenate()(my_inputs.values())
    dense = layers.Dense(units=1, input_shape=(1,), name='dense_layer', activation=tf.sigmoid)
    dense_output = dense(concatenated_inputs)
    """创建并编译一个简单的分类模型."""
    my_outputs = {
        'dense': dense_output,
    }
    model = tf.keras.Model(inputs=my_inputs, outputs=my_outputs)

    # 调用compile方法将层构造为TensorFlow可以执行的模型。注意,这里使用的损失函数(sigmoid)与在回归中使用的(ReLU)不同。
    model.compile(optimizer=tf.keras.optimizers.experimental.RMSprop(learning_rate=my_learning_rate),
                  loss=tf.keras.losses.BinaryCrossentropy(),
                  metrics=METRICS)
    return model


# 定义模型训练函数
def train_model(model, dataset, epochs, label_name,
                batch_size=None, shuffle=True):
    """将数据集输入到模型中以便对其进行训练."""

    # tf.keras.Model.fit的x参数可以是数组列表,其中每个数组包含一个特征的数据。
    # 在这里,我们传递数据集中的每一列。注意,feature_layer将过滤掉这些列中的大部分,只留下所需的列及其表示形式作为特征。
    features = {name: np.array(value) for name, value in dataset.items()}
    label = np.array(features.pop(label_name))
    history = model.fit(x=features, y=label, batch_size=batch_size,
                        epochs=epochs, shuffle=shuffle)

    # 将轮次列表与历史的其余部分分开存储
    epochs = history.epoch

    # 隔离每个轮次的分类结果
    hist = pd.DataFrame(history.history)

    return epochs, hist


print("Defined the create_model and train_model functions.")


# 定义打印函数
def plot_curve(epochs, hist, list_of_metrics):
    """绘制一个或多个分类度量相对于训练轮次的曲线"""

    plt.figure()
    plt.xlabel("Epoch")
    plt.ylabel("Value")

    for m in list_of_metrics:
        x = hist[m]
        plt.plot(epochs[1:], x[1:], label=m)

    plt.legend()


print("Defined the plot_curve function.")

# 指定超参数
learning_rate = 0.001
epochs = 20
batch_size = 100
classification_threshold = 0.35
label_name = "median_house_value_is_high"

# 建立模型将衡量的指标:准确度、精度、召回率
METRICS = [
    tf.keras.metrics.BinaryAccuracy(name='accuracy',
                                    threshold=classification_threshold),
    tf.keras.metrics.Precision(thresholds=classification_threshold,
                               name='precision'
                               ),
    tf.keras.metrics.Recall(thresholds=classification_threshold,
                            name="recall"),
]

# 建立模型的拓扑
my_model = create_model(inputs, learning_rate, METRICS)
# 基于训练数据训练模型
epochs, hist = train_model(my_model, train_df_norm, epochs,
                           label_name, batch_size)

# 绘制模型准确度、精度、召回率指标和训练轮次的关系图
list_of_metrics_to_plot = ['accuracy', "precision", "recall"]
plot_curve(epochs, hist, list_of_metrics_to_plot)

print("\n: Evaluate the new model against the test set:")

执行结果如下所示:

 

11.任务三:试验分类阈值

在“调用创建、训练和绘图功能”中的代码单元中尝试不同的分类阈值。尝试寻找一个分类阈值,使其产生最高的准确性?经过尝试,我们发现,将其设置为 0.52 时,可以得到较高的准确性。

classification_threshold = 0.52

 

12.任务四:总结模型性能(如果时间允许)

再添加一个指标——AUC,试图总结模型的总体性能。将代码单元换成如下代码:

# 指定超参数
learning_rate = 0.001
epochs = 20
batch_size = 100
label_name = "median_house_value_is_high"

# AUC 作为模型评估指标
METRICS = [
    tf.keras.metrics.AUC(num_thresholds=100, name='auc'),
]

# 创建模型拓扑
my_model = create_model(inputs, learning_rate, METRICS)

# 基于训练数据集训练模型
epochs, hist = train_model(my_model, train_df_norm, epochs,
                           label_name, batch_size)

# 打印AUC与训练轮次的关系图
list_of_metrics_to_plot = ['auc']
plot_curve(epochs, hist, list_of_metrics_to_plot)

运行结果如下所示:

 

13.参考文献

 链接-https://developers.google.cn/machine-learning/crash-course/classification/programming-exercise

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/705519.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于matlab深度学习的多光谱图像语义分割(附源码)

一、前言 此示例演示如何使用 U-Net 对具有七个通道的多光谱图像执行语义分割。 语义分割涉及用类标记图像中的每个像素。语义分割的一个应用是跟踪森林砍伐,即森林覆盖率随时间的变化。环境机构跟踪森林砍伐,以评估和量化一个地区的环境和生态健康状况…

Flink消费kafka出现空指针异常

文章目录 出现场景:表现:问题:解决: tombstone : Kafka中提供了一个墓碑消息(tombstone)的概念,如果一条消息的key不为null,但是其value为null,那么此消息就是墓碑消息. …

echarts tooltip自定义线条样式及数据提示框内容

option {......tooltip: {trigger: axis,borderWidth: 0, // 去除数据提示框默认的边框axisPointer: {lineStyle: { // 设置hover时竖线样式color: {type: linear,x: 0,y: 0,x2: 0,y2: 1,colorStops: [{offset: 0,color: rgba(128,200,244,0) // 0% 处的颜色},{offset: 1,colo…

【40000字】!最适合新手的Springboot+Vue项目

更多文章:https://mp.weixin.qq.com/mp/appmsgalbum?__bizMzg2NDY3NjY5NA&actiongetalbum&album_id2053253027934863360#wechat_redirect hello我是索奇,本套项目对应bilibili视频,大家可以结合视频看哈,有些基础的只看…

2022年系统架构师论文(回忆版)

2022年11月6日,全国计算机等级下半年考试,在疫情压力下如期举行。 北京市软件架构师考试地点在北京市工贸技师学院(机电分院),地址:海淀区北四环北路132号(金泰海博大酒店北侧) 查看…

网络安全(黑客)自学笔记

建议一:黑客七个等级 黑客,对很多人来说充满诱惑力。很多人可以发现这门领域如同任何一门领域,越深入越敬畏,知识如海洋,黑客也存在一些等级,参考知道创宇 CEO ic(世界顶级黑客团队 0x557 成员…

chatgpt赋能python:吐血推荐的Python编程好玩的代码

吐血推荐的Python编程好玩的代码 近年来,Python 成为了全球最受欢迎的编程语言之一。Python 的简洁明了,易学易用,使得越来越多的开发者选择了 Python。Python 的生态系统非常丰富,有很多丰富有趣的库和代码可以供我们玩耍。在本…

使用MySQL根据原型字段创建表结构

⭐️ 不爱生姜不吃醋,原创不易,转载请注明原链接 ❗️ 注:本文写的是基于MySQL对数据库表结构进行的操作(DDL) 文章目录 一、数据库1.基本概念2.关系型数据库(RDBMS)3.数据模型4.SQL通用语法5.SQL分类 二.创建表结构1.…

关于nlohmann::json的简单使用

nlohmann::json的使用非常简单&#xff0c;只需要包含.hpp文件即可&#xff0c;这是它的官网https://github.com/nlohmann/json 简单使用&#xff1a; #include "json.hpp" #include <iostream>using Info nlohmann::json;int main() {Info info;std::cout &…

Java面试Day11

1. MySQL 事务有哪些隔离级别、分别有什么特点&#xff0c;以及 MySQL 的默认隔离级别是什么&#xff1f; 在MySQL中事务的隔离级别是为了解决常见的并发问题&#xff0c;在保证数据库性能的同时保持事务的隔离性&#xff0c;常见的并发问题有&#xff1a; 脏读&#xff1a;如果…

利用nginx/apache代理wss 实现 小程序 端口 反向代理

除了用Workerman自身的SSL&#xff0c;也可以利用nginx/apache作为wss代理转发给workerman 我就是栽在这大坑里&#xff08;nginx/apache代理wss&#xff0c;workerman部分就不要设置ssl&#xff0c;否则将无法连接&#xff0c;两个方法2选1&#xff09;官方推荐用nginx/apach…

基于matlab基于预训练的膨胀双流卷积神经网络的视频分类器执行活动识别(附源码)

一、前言 此示例首先展示了如何使用基于预训练的膨胀 3-D &#xff08;I3D&#xff09; 双流卷积神经网络的视频分类器执行活动识别&#xff0c;然后展示了如何使用迁移学习来训练此类视频分类器使用 RGB 和来自视频的光流数据 [1]。 基于视觉的活动识别涉及使用一组视频帧预…

数据结构07:查找[C++][红黑二叉排序树RBT]

图源&#xff1a;文心一言 | 提词&#xff1a;动漫风格 红黑树 少女#创意图# 考研笔记整理1.7w字&#xff0c;但是删除操作的代码是有一点问题的{无法正确处理红色结点的删除}&#xff0c;其它功能可正常使用&#xff0c;请小伙伴注意~~&#x1f95d;&#x1f95d; 第1版&…

【线程池】线程池的ctl属性详解

目录 一、ctl介绍 二、线程池ctl源码 三、线程池ctl分析 1、private static int ctlOf(int rs, int wc) { return rs | wc; } 2、private final AtomicInteger ctl new AtomicInteger(ctlOf(RUNNING, 0)); 3、private static int runStateOf(int c) { return c &am…

TensorFlow框架

TensorFlow框架 本文目录&#xff1a; 一、通过代码了解TensorFlow结构 1.1、TensorFlow实现一个加法运算代码 1.1.1、原生python加法运算 1.1.2、TensorFlow实现加法运算 1.1.3、TensorFlow实现加法运算 1.2、TensorFlow的Hello World 二、TensorFlow架构图 三、Tenso…

WebRTC Docker容器部署方案

文章目录 WebRTC简介WebRTC Docker容器部署优势方案&#xff08;mpromonet/webrtc-streamer&#xff09;步骤 WebRTC简介 WebRTC&#xff08;Web Real-Time Communication&#xff09;是一种开放的实时通信技术&#xff0c;它允许浏览器之间进行音频、视频和数据的实时传输。W…

第九十二天学习记录:C++核心:类和对象Ⅰ(五星重要)

C面向对象的三大特性为&#xff1a;封装、继承、多态 C认为万事万物都皆为对象&#xff0c;对象上有其属性和行为 封装 封装的意义 封装是C面向对象三大特性之一 封装的意义&#xff1a; 1、将属性和行为作为一个整体&#xff0c;表现生活中的事物 2、将属性和行为加以权限…

js判断文件类型详解

js判断文件类型详解 通过file的type属性判断 <input type"file" onchange"onchangecb(this)" /> <script> function onchangecb(e) {const file e.files[0];console.log(file.type); } </script>像html中input标签&#xff0c;就是根…

地下水数值模拟-Visual modflow Flex软件应用

地下水&#xff08;ground water&#xff09;&#xff0c;是指赋存于地面以下岩石空隙中的水&#xff0c;狭义上是指地下水面以下饱和含水层中的水。在国家标准《水文地质术语》&#xff08;GB/T 14157-93&#xff09;中&#xff0c;地下水是指埋藏在地表以下各种形式的重力水。…

基于协议判断目标机器是否出网

内网渗透中时常会碰到一些不出网的主机&#xff0c;不出网的原因有很多&#xff0c;如常见的有&#xff1a;没有设置网关、系统防火墙或者其他设备设置了出入站限制&#xff0c;只允许特定协议或端口出网等&#xff0c;遇到这种情况时可以用以下命令测试目标主机允许哪些协议出…