神经网络基础-价格分类案例

news2025/1/18 20:12:06

文章目录

    • 1. 需求分析
    • 2. 导入所需工具包
    • 3. 构建数据集
    • 4. 构建分类网络模型
    • 5. 训练模型
    • 6. 模型训练
    • 7. 评估模型
    • 8. 模型优化

学习目标:

  1. 掌握构建分类模型流程
  2. 动手实践整个过程

1. 需求分析

小明创办了一家手机公司,他不知道如何估算手机产品的价格。为了解决这个问题,他收集了多家公司的手机销售数据。该数据为二手手机的各个性能的数据,最后根据这些性能得到4个价格区间,作为这些二手手机售出的价格区间。主要包括:

battery_power电池一次可存储的电量,单位:毫安/时
blue是否有蓝牙
clock_speed微处理器执行指令的速度
dual_sim是否支持双卡
fc前置摄像头百万像素
four_g是否有4G
int_memory内存(GB)
m_dep移动深度(cm)
mobile_wt手机重量
n_cores处理器内核数
pc主摄像头百万像素
px_height像素分辨率高度
px_width像素分辨率宽度
ram随机存储器(兆字节)
sc_h手机屏幕高度(cm)
sc_w手机屏幕宽度(cm)
talk_time一次充电持续时长
three_g是否有3G
touch_screen是否有触屏控制
wifi是否能连wifi
price_range价格区间(0,1,2,3)

我们需要帮助小明找出手机的功能(例如:RAM等)与其售价之间的某种关系。我们可以使用机器学习的方法来解决这个问题,也可以构建一个全连接的网络。

需要注意的是: 在这个问题中,我们不需要预测实际价格,而是一个价格范围,它的范围使用 0、1、2、3 来表示,所以该问题也是一个分类问题。接下来我们还是按照四个步骤来完成这个任务:

  • 准备训练集数据

  • 构建要使用的模型

  • 模型训练

  • 模型预测评估

2. 导入所需工具包

# 导入相关模块
import torch
from torch.utils.data import TensorDataset
from torch.utils.data import DataLoader
import torch.nn as nn
import torch.optim as optim
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import time

3. 构建数据集

数据共有 2000 条, 其中 1600 条数据作为训练集, 400 条数据用作测试集。 我们使用 sklearn 的数据集划分工作来完成。并使用 PyTorch 的 TensorDataset 来将数据集构建为 Dataset 对象,方便构造数据集加载对象。

#1. 导入相关模块
import torch
from torch.utils.data import TensorDataset
from torch.utils.data import DataLoader
import torch.nn as nn
import torch.optim as optim
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import time

# 构建数据集
def load_dataset():
    # 使用pandas 读取数据
    data = pd.read_csv('data/手机价格预测.csv')
    # 特征值和目标值
    x,y = data.iloc[:,:-1],data.iloc[:,-1]
    # 类型转换:特征值,目标值
    x = x.astype(np.float32)
    y = y.astype(np.int64)
    # 划分训练集和测试集
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=88)
    # 构建数据集,转换为pytorch格式
    train_dataset = TensorDataset(torch.from_numpy(x_train.values), torch.from_numpy(y_train.values))
    test_dataset = TensorDataset(torch.from_numpy(x_test.values), torch.from_numpy(y_test.values))
    #返回结果
    return train_dataset, test_dataset,x_train.shape[1],len(np.unique(y))

if __name__ == '__main__':
    train_dataset, test_dataset,input_dim,class_num = load_dataset()
    print("输入特征数:",input_dim)
    print("分类个数:",class_num)

输出结果为:

输入特征数: 20
分类个数: 4

4. 构建分类网络模型

构建全连接神经网络来进行手机价格分类,该网络主要由三个线性层来构建,使用relu激活函数。

网络共有 3 个全连接层, 具体信息如下:

  1. 第一层: 输入为维度为 20, 输出维度为: 128
  2. 第二层: 输入为维度为 128, 输出维度为: 256
  3. 第三层: 输入为维度为 256, 输出维度为: 4
# 构建网络模型
class PhonePriceModel(nn.Module):
    def __init__(self,input_dim,output_dim):
        super(PhonePriceModel, self).__init__()
        # 1. 第一层: 输入为维度为 20, 输出维度为: 128
        self.linear1 = nn.Linear(input_dim, 128)
        # 2. 第二层: 输入为维度为 128, 输出维度为: 256
        self.linear2 = nn.Linear(128, 256)
        # 3. 第三层: 输入为维度为 256, 输出维度为: 4
        self.linear3 = nn.Linear(256, output_dim)

    def forward(self, x):
        # 前向传播过程
        x = torch.relu(self.linear1(x))
        x = torch.relu(self.linear2(x))
        output = self.linear3(x)
        # 获取数据结果
        return output

if __name__ == '__main__':
    train_dataset, test_dataset,input_dim,class_num = load_dataset()
    print("输入特征数:",input_dim)
    print("分类个数:",class_num)
    # 模型实例化
    model = PhonePriceModel(input_dim,class_num)

5. 训练模型

网络编写完成之后,我们需要编写训练函数。所谓的训练函数,指的是输入数据读取、送入网络、计算损失、更新参数的流程,该流程较为固定。我们使用的是多分类交叉生损失函数、使用 SGD 优化方法。最终,将训练好的模型持久化到磁盘中。

# 模型训练过程
def train(train_dataset,input_dim,class_num):
    # 固定随机数种子
    torch.manual_seed(0)
    # 初始化模型
    model = PhonePriceModel(input_dim,class_num)
    # 损失函数
    criterion = nn.CrossEntropyLoss()
    # 优化方法
    optimizer = optim.SGD(model.parameters(), lr=1e-3)
    # 训练轮数
    num_epochs = 50
    # 遍历轮数
    for epoch_idx in range(num_epochs):
        # 初始化数据加载器
        dataloader = DataLoader(train_dataset, batch_size=8, shuffle=True)
        # 训练时间
        start = time.time()
        # 计算损失
        total_loss = 0.0
        total_num = 1
        # 遍历每个batch数据进行处理
        for x,y in dataloader:
            # 将数据送入网络中进行预测
            output = model(x)
            # 计算损失
            loss = criterion(output, y)
            #梯度清零
            optimizer.zero_grad()
            # 方向传播
            loss.backward()
            # 参数更新
            optimizer.step()
            # 损失计算
            total_num += 1
            total_loss += loss.item()
        # 打印损失变换结果
        print('epoch: %4s loss: %.2f, time: %.2fs' % (epoch_idx + 1, total_loss / total_num, time.time() - start))

    # 保存模型
    torch.save(model.state_dict(), 'model/phone.ptn')

6. 模型训练

if __name__ == '__main__':
    train_dataset, test_dataset,input_dim,class_num = load_dataset()
    print("输入特征数:",input_dim)
    print("分类个数:",class_num)
    # 模型训练过程
    train(train_dataset,input_dim,class_num)

输出结果:

epoch:    1 loss: 13.31, time: 0.25s
epoch:    2 loss: 0.96, time: 0.24s
epoch:    3 loss: 0.90, time: 0.24s
epoch:    4 loss: 0.89, time: 0.25s
epoch:    5 loss: 0.86, time: 0.26s
...
epoch:   46 loss: 0.68, time: 0.25s
epoch:   47 loss: 0.69, time: 0.26s
epoch:   48 loss: 0.68, time: 0.28s
epoch:   49 loss: 0.69, time: 0.24s
epoch:   50 loss: 0.69, time: 0.24s

7. 评估模型

使用训练好的模型,对未知的样本的进行预测的过程。我们这里使用前面单独划分出来的验证集来进行评估。

# 4 评估模型
def test(test_dataset,input_dim,class_num):
    # 加载模型和训练好的网络参数
    model = PhonePriceModel(input_dim,class_num)

    model.load_state_dict(torch.load('model/phone.ptn',weights_only=False))
    # 构建加载器
    dataloader = DataLoader(test_dataset, batch_size=8, shuffle=True)
    # 评估测试集
    correct = 0
    # 遍历测试集中的数据
    for x,y in dataloader:
        # 将其送入网络中
        output = model(x)
        # 获取类别结果
        y_pred = torch.argmax(output, dim=1)
        # 获取预测正确的个数
        correct += (y_pred == y).sum().sum()
    # 求预测精度
    print('Acc: %.5f' % (correct.item() / len(test_dataset)))
if __name__ == '__main__':
    train_dataset, test_dataset,input_dim,class_num = load_dataset()
    print("输入特征数:",input_dim)
    print("分类个数:",class_num)
    # 评估模型
    test(test_dataset,input_dim,class_num)

输出结果:

Acc: 0.62500

8. 模型优化

我们前面的网络模型在测试集的准确率为: 0.54750, 我们可以通过以下方面进行调优:

  1. 优化方法由 SGD 调整为 Adam
  2. 学习率由 1e-3 调整为 1e-4
  3. 对数据数据进行标准化
  4. Dropout 正则化
  5. 调整训练轮次
# 使用Adam方法优化网络
#1. 导入相关模块
import torch
from tensorboard import summary
from torch.utils.data import TensorDataset
from torch.utils.data import DataLoader
import torch.nn as nn
import torch.optim as optim
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import time

#2. 构建数据集
def load_dataset():
    # 使用pandas 读取数据
    data = pd.read_csv('data/手机价格预测.csv')
    # 特征值和目标值
    x,y = data.iloc[:,:-1],data.iloc[:,-1]
    # 类型转换:特征值,目标值
    x = x.astype(np.float32)
    y = y.astype(np.int64)
    # 划分训练集和测试集
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=88)
    # 数据标准化
    scaler = StandardScaler()
    x_train = scaler.fit_transform(x_train)
    x_test = scaler.fit_transform(x_test)
    x_train = torch.tensor(x_train,dtype=torch.float32)
    x_test = torch.tensor(x_test,dtype=torch.float32)
    # 构建数据集,转换为pytorch格式
    train_dataset = TensorDataset(x_train, torch.from_numpy(y_train.values))
    test_dataset = TensorDataset(x_test, torch.from_numpy(y_test.values))
    #返回结果
    return train_dataset, test_dataset,x_train.shape[1],len(np.unique(y))
#2. 构建网络模型
class PhonePriceModel(nn.Module):
    def __init__(self,input_dim,output_dim,p_dropout=0.4):
        super(PhonePriceModel, self).__init__()
        # 第一层: 输入为维度为 20, 输出维度为: 128
        self.linear1 = nn.Linear(input_dim, 128)
        # Dropout优化
        self.dropout = nn.Dropout(p_dropout)
        # 第二层: 输入为维度为 128, 输出维度为: 256
        self.linear2 = nn.Linear(128, 256)
        # Dropout优化
        self.dropout = nn.Dropout(p_dropout)
        # 第三层: 输入为维度为 256, 输出维度为: 4
        self.linear3 = nn.Linear(256, output_dim)

    def forward(self, x):
        # 前向传播过程
        x = torch.relu(self.linear1(x))
        x = torch.relu(self.linear2(x))
        output = self.linear3(x)
        # 获取数据结果
        return output

# 3. 模型训练过程
def train(train_dataset,input_dim,class_num):
    # 固定随机数种子
    torch.manual_seed(0)
    # 初始化模型
    model = PhonePriceModel(input_dim,class_num)
    # 损失函数
    criterion = nn.CrossEntropyLoss()
    # 优化方法
    # optimizer = optim.SGD(model.parameters(), lr=1e-3)
    # Adam优化方法 调整学习率为 lr=1e-4
    optimizer = torch.optim.Adam(model.parameters(), lr=1e-4, betas=(0.9, 0.99))
    # 训练轮数 100 - 0.9075 50 - 0.9125
    num_epochs = 50
    # 遍历轮数
    for epoch_idx in range(num_epochs):
        # 初始化数据加载器
        dataloader = DataLoader(train_dataset, batch_size=8, shuffle=True)
        # 训练时间
        start = time.time()
        # 计算损失
        total_loss = 0.0
        total_num = 1
        # 遍历每个batch数据进行处理
        for x,y in dataloader:
            # 将数据送入网络中进行预测
            output = model(x)
            # 计算损失
            loss = criterion(output, y)
            #梯度清零
            optimizer.zero_grad()
            # 方向传播
            loss.backward()
            # 参数更新
            optimizer.step()
            # 损失计算
            total_num += 1
            total_loss += loss.item()
        # 打印损失变换结果
        print('epoch: %4s loss: %.2f, time: %.2fs' % (epoch_idx + 1, total_loss / total_num, time.time() - start))

    # 保存模型
    torch.save(model.state_dict(), 'model/phone2.ptn')
# 4 评估模型
def test(test_dataset,input_dim,class_num):
    # 加载模型和训练好的网络参数
    model = PhonePriceModel(input_dim,class_num)

    model.load_state_dict(torch.load('model/phone2.ptn',weights_only=False))
    # 构建加载器
    dataloader = DataLoader(test_dataset, batch_size=8, shuffle=True)
    # 评估测试集
    correct = 0
    # 遍历测试集中的数据
    for x,y in dataloader:
        # 将其送入网络中
        output = model(x)
        # 获取类别结果
        y_pred = torch.argmax(output, dim=1)
        # 获取预测正确的个数
        correct += (y_pred == y).sum().sum()
    # 求预测精度
    print('Acc: %.5f' % (correct.item() / len(test_dataset)))
if __name__ == '__main__':
    train_dataset, test_dataset,input_dim,class_num = load_dataset()
    print("输入特征数:",input_dim)
    print("分类个数:",class_num)
    # 模型训练
    train(train_dataset,input_dim,class_num)
    test(test_dataset,input_dim,class_num)

这里我们调整 Adam方法优化梯度下降,学习率调整为1e-4,样本数据采用标准化处理。采用Dropout正则化。最后输出结果:

Acc: 0.91250

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

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

相关文章

unity2022以上导出到AndroidStudio后更新步骤

1、unity里面Export出unityLibrary 2、导出apk,里面才包含libil2cpp(新版unity无法直接导出libil2cpp 3、注释AS项目app下的build.gradle里面包含unityLibrary的代码 4、注释AS项目settings.gradle包含unityLibrary的代码 5、删除AS项目里面的unityLibrary文件夹 6、…

LabVIEW串口通信调试与数据接收问题

在使用LabVIEW进行串口通信时,常常会遇到无法接收数据的情况。这可能与串口设置、连接、设备响应等多方面因素相关。本文将详细讨论如何使用LabVIEW进行串口通信,并提供常见问题的排查与解决方法,帮助用户更高效地进行数据接收调试。通过调整…

Java并发编程——线程池(基础,使用,拒绝策略,命名,提交方式,状态)

我是一个计算机专业研0的学生卡蒙Camel🐫🐫🐫(刚保研) 记录每天学习过程(主要学习Java、python、人工智能),总结知识点(内容来自:自我总结网上借鉴&#xff0…

【HarmonyOS NEXT】鸿蒙跳转华为应用市场目标APP下载页

【HarmonyOS NEXT】鸿蒙跳转华为应用市场目标APP下载页 一、问题背景: 如今,大家都离不开各种手机应用。随着鸿蒙系统用户越来越多,大家都希望能在鸿蒙设备上快速找到想用的 APP。华为应用市场里有海量的 APP,但之前从鸿蒙设备进…

智能物流升级利器——SAIL-RK3576核心板AI边缘计算网关设计方案(一)

近年来,随着物流行业智能化和自动化水平不断提升,数据的实时处理与智能决策成为推动物流运输、仓储管理和配送优化的重要手段。传统的集中式云平台虽然具备强大计算能力,但高延迟和带宽限制往往制约了物流现场的即时响应。为此,我…

nacos环境搭建以及SpringCloudAlibaba脚手架启动环境映射开发程序

1:下载nacos 地址:https://github.com/alibaba/nacos/tags 2:选择server的zip包下载 3:启动mysql服务,新建数据库:nacos_yh 4:解压下载的nacos_server 进入conf目录 5:mysql运行sql脚本变得到下面的表 6&a…

Java中线程的学习

目录​​​​​​​ 程序,进程,线程 创建线程 继承Thread类 实现Runnable接口 Thread类中方法 线程优先级 线程状态 多线程的概念 线程同步 在Java代码中实现同步 以下代码使用继承Thread方式实现 以下代码使用实现Runnable方式实现 Lock(锁&#xf…

HTTP/HTTPS ⑤-CA证书 || 中间人攻击 || SSL/TLS

这里是Themberfue ✨上节课我们聊到了对称加密和非对称加密,实际上,单纯地非对称加密并不能保证数据不被窃取,我们还需要一个更加重要的东西——证书 中间人攻击 通过非对称加密生成私钥priKey和公钥pubKey用来加密对称加密生成的密钥&…

leetcode:205. 同构字符串(python3解法)

难度:简单 给定两个字符串 s 和 t ,判断它们是否是同构的。 如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。 每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字…

从epoll事件的视角探讨TCP:三次握手、四次挥手、应用层与传输层之间的联系

目录 一、应用层与TCP之间的联系 二、 当通信双方中的一方如客户端主动断开连接时,仅是在客户端的视角下连接已经断开,在服务端的眼中,连接依然存在,为什么?——触发EPOLLRDHUP事件:对端关闭连接或停止写…

EMS专题 | 守护数据安全:数据中心和服务器机房环境温湿度监测

您需要服务器机房温度监测解决方案吗? 服务器机房是企业中用于存储、管理和维护服务器及其相关组件的设施。服务器机房通常位于数据中心内,是一个专门设计的物理环境,旨在确保服务器的稳定运行和数据的安全性。服务器机房主要起到存储和管理数…

运输层安全协议SSL

安全套接字层 SSL (Secure Socket Layer) SSL 作用在端系统应用层的 HTTP 和运输层之间,在 TCP 之上建立起一个安全通道,为通过 TCP 传输的应用层数据提供安全保障。 应用层使用 SSL 最多的就是 HTTP,但 SSL 并非仅用于 HTTP,而是…

网络安全面试题汇总(个人经验)

1.谈一下SQL主从备份原理? 答:主将数据变更写入自己的二进制log,从主动去主那里去拉二进制log并写入自己的二进制log,从而自己数据库依据二进制log内容做相应变更。主写从读 2.linux系统中的计划任务crontab配置文件中的五个星星分别代表什么&#xff…

51单片机 DS18B20温度储传感器

DS18B20温度传感器 64-BITROM:作为器件地址,用于总线通信的寻址,是唯一的,不可更改 SCRATCHPAD(暂存器):用于总线的数据交互 EEPROM:用于保存温度触发阈值和配置参数 暂存器 单总线…

如何保证光谱相机的稳定性和可靠性

光学系统设计与制造 高质量光学元件:采用高精度研磨和镀膜的透镜、棱镜、光栅等光学元件。优质的透镜可以减少像差和色差,确保光线准确聚焦;高质量的镀膜能够提高光学元件的透光率,降低反射损失,并且增强对不同波段光…

【芯片封测学习专栏 -- 2D | 2.5D | 3D 封装的区别和联系】

请阅读【嵌入式开发学习必备专栏 Cache | MMU | AMBA BUS | CoreSight | Trace32 | CoreLink | ARM GCC | CSH】 文章目录 Overview线键合(wire-bonding)封装FOWLP2D封装2.5D 封装硅通孔(TSV)硅中介层无TSV的2.5D 3D封装 Overview 我们先要了解一下&…

Apache搭建https服务器

Apache搭建https服务器 REF: 使用OpenSSL自建一个HTTPS服务

element-ui textarea备注 textarea 多行输入框

发现用这个组件,为了给用户更好的体验,要加下属性 1. 通过设置 autosize 属性可以使得文本域的高度能够根据文本内容自动进行调整,并且 autosize 还可以设定为一个对象,指定最小行数和最大行数。:autosize"{ minRows: 3, ma…

图论1-问题 C: 算法7-6:图的遍历——广度优先搜索

题目描述 广度优先搜索遍历类似于树的按层次遍历的过程。其过程为:假设从图中的某顶点v出发,在访问了v之后依次访问v的各个未曾被访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先…

基于vue框架的的校园心理咨询室系统63w37(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表 项目功能:用户,咨询师,文章类型,心理文章,在线咨询,典型案例,线下预约,取消预约 开题报告内容 基于Vue框架的校园心理咨询室系统开题报告 一、研究背景与意义 随着社会的快速发展和竞争的加剧,校园中的学生面临着越来越多的心理压力…