news 2026/8/13 8:44:58

08-案例-手机价格分类

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
08-案例-手机价格分类

1. 需求分析

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

2. 数据说明

数据来源:手机价格分类_数据集-阿里云天池

字段名字段说明
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)

3. 建模

import time import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from torch import nn, optim from torch.utils.data import TensorDataset, DataLoader import torch from torchsummary import summary

3.1 准备数据

# todo 1: 数据准备 def load_data(): # 1. 读取数据 data = pd.read_csv('./data/mobile_phone_price_cls/train.csv') # print(data.head()) # print(data.shape) # print(data.info()) # 2. 提取特征和标签 x, y = data.iloc[:, :-1], data.iloc[:, -1] x = x.astype(np.float32) # 转换数据类型 # print(x.head(), y[:5]) # 3. 划分训练集和测试集 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=11, stratify=y) # 4. 把数据集转换成张量(数据->张量Tensor->数据集TensorDataset->数据加载器DataLoader(后续再做)) 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)) print(f'训练集对象:{train_dataset}') print(f'测试集对象:{test_dataset}') # 5. 获取特征数量和标签数量 input_dim = x_train.shape[1] # 输入的特征数量 output_dim = len(np.unique(y)) # 输出的标签类别数量 print(f'输入的特征数量:{input_dim}') print(f'输出的标签数量:{output_dim}') return train_dataset, test_dataset, input_dim, output_dim

3.2 搭建神经网络

# todo 2: 搭建神经网络 class MobilePhonePriceClassification(torch.nn.Module): # 1. 初始化 def __init__(self, input_dim, output_dim): # 输入特征数量,输出标签类别数量 # 1.1 继承父类初始化方法 super().__init__() # 1.2 定义神经网络 # 1.2.1 隐藏层 self.linear1 = nn.Linear(input_dim, 128) self.linear2 = nn.Linear(128, 256) # 1.2.2 输出层 self.output = nn.Linear(256, output_dim) # 2. 前向传播 def forward(self, x): # 2.1 隐藏层: relu x = torch.relu(self.linear1(x)) x = torch.relu(self.linear2(x)) # 2.2 输出层: softmax # 这里不用写成softmax(x),因为nn.CrossEntropyLoss()里面已经包含了softmax() x = self.output(x) # 加权求和 return x

3.3 模型训练与保存

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

# todo 3: 模型训练 def train(train_dataset, input_dim, output_dim): # 1. 获取数据加载器DataLoader # 参1: 数据集;参2: 批次大小;参数3: 是否打乱数据(训练集打乱,测试集不打乱) train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True) # 2. 创建模型 model = MobilePhonePriceClassification(input_dim, output_dim) # 3. 创建损失函数:多分类交叉熵损失函数 criterion = nn.CrossEntropyLoss() # 4. 创建优化器 optimizer = optim.SGD(model.parameters(), lr=0.001) # 5. 训练模型 # 5.1 训练轮数 epochs = 50 # 5.2 开始每轮的训练 for epoch in range(epochs): # 5.2.1 记录每次训练的损失值和批次数 total_loss, batch_num = 0.0, 0 # 5.2.2 记录训练开始的时间 start = time.time() # 5.2.3 开始本轮的各批次训练 for x, y in train_loader: # 5.2.3.1 切换模型(状态) model.train() # 训练模式 # 5.2.3.2 模型预测 y_pred = model(x) # 5.2.3.3 计算损失值 loss = criterion(y_pred, y) # 5.2.3.4 梯度清零,反向传播,优化参数 optimizer.zero_grad() loss.backward() optimizer.step() # 5.2.3.5 累计损失值和批次数 total_loss += loss.item() # 把本轮的每批次16条的平均损失值累加起来 batch_num += 1 # 5.2.4 本轮训练结束,打印训练信息 print(f'epoch: {epoch + 1}, loss: {total_loss / batch_num:.4f}, time: {time.time() - start:.2f}s') # 6. 此处多轮训练结束,保存模型(参数) # 参1: 模型参数信息;参2: 模型保存路径 torch.save(model.state_dict(), './model/mobile_phone_price_cls.pth')

3.4 模型预测和评估

# todo 4: 模型测试 def evaluate(test_dataset, input_dim, output_dim): # 1. 创建神经网络分类对象 model = MobilePhonePriceClassification(input_dim, output_dim) # 2. 加载模型参数 model.load_state_dict(torch.load('./model/mobile_phone_price_cls.pth')) # 3. 创建数据加载器DataLoader test_loader = DataLoader(test_dataset, batch_size=16, shuffle=False) # 4. 记录预测正确的样本个数 correct = 0 # 5. 从数据加载器中获取每批次的数据 for x, y in test_loader: # 5.1 切换测试模式 model.eval() # 5.2 模型预测 y_pred = model(x) # print(f'y_pred: {y_pred}') # 加权求和的结果 # 5.3 根据加权求和,得到类别,用argmax()获取最大值对应的下标,即类别 y_pred = torch.argmax(y_pred, dim=1) print(f'预测类别:{y_pred}') # 如果值全都一样,可能是学习率太大了,调小试一下 # 5.4 统计预测正确的样本个数 correct += (y_pred == y).sum().item() # 6. 模型预测结束,计算准确率 print(f'准确率:{correct / len(test_dataset):.4f}')

3.5 运行

if __name__ == '__main__': # 1. 数据准备 train_dataset, test_dataset, input_dim, output_dim = load_data() # 2. 搭建神经网络 model = MobilePhonePriceClassification(input_dim, output_dim) # 2.1 计算模型参数 summary(model, input_size=(16, input_dim)) # input_size=(batch_size, input_dim), 每批16条,每条20个特征 # 3. 模型训练 train(train_dataset, input_dim, output_dim) # 4. 模型评估 evaluate(test_dataset, input_dim, output_dim)

3.6 网络优化

""" 案例-手机价格分类 网络优化思路: 1. 数据标准化/批量归一正则化 2. 梯度下降法优化:SGD -> Adam 3. 调整学习率:0.001 -> 0.0001 4. 增加网络层数、神经元个数:增加两层 5. 增加训练轮数:50 -> 200 结果: 0. 不优化:ACC=0.585 1. 仅优化1:ACC=0.67 2. 仅优化2:ACC=0.71 3. 仅优化3:ACC=0.7975 4. 仅优化4:ACC=0.6825 5. 仅优化5:ACC=0.6450 6. 同时优化12345:ACC=0.9175 --> 完美!! """ import time import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from torch import nn, optim from torch.utils.data import TensorDataset, DataLoader import torch from torchsummary import summary # todo 1: 数据准备 def load_data(): # 1. 读取数据 data = pd.read_csv('./data/mobile_phone_price_cls/train.csv') # print(data.head()) # print(data.shape) # print(data.info()) # 2. 提取特征和标签 x, y = data.iloc[:, :-1], data.iloc[:, -1] x = x.astype(np.float32) # 转换数据类型 # print(x.head(), y[:5]) # 3. 划分训练集和测试集 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=11, stratify=y) # todo: 优化1: 数据标准化 transfer = StandardScaler() x_train = transfer.fit_transform(x_train) x_test = transfer.transform(x_test) # 4. 把数据集转换成张量(数据->张量Tensor->数据集TensorDataset->数据加载器DataLoader(后续再做)) train_dataset = TensorDataset(torch.from_numpy(x_train), torch.from_numpy(y_train.values)) test_dataset = TensorDataset(torch.from_numpy(x_test), torch.from_numpy(y_test.values)) print(f'训练集对象:{train_dataset}') print(f'测试集对象:{test_dataset}') # 5. 获取特征数量和标签数量 input_dim = x_train.shape[1] # 输入的特征数量 output_dim = len(np.unique(y)) # 输出的标签类别数量 print(f'输入的特征数量:{input_dim}') print(f'输出的标签数量:{output_dim}') return train_dataset, test_dataset, input_dim, output_dim # todo 2: 搭建神经网络 class MobilePhonePriceClassification(torch.nn.Module): # 1. 初始化 def __init__(self, input_dim, output_dim): # 输入特征数量,输出标签类别数量 # 1.1 继承父类初始化方法 super().__init__() # 1.2 定义神经网络 # 1.2.1 隐藏层 self.linear1 = nn.Linear(input_dim, 128) self.linear2 = nn.Linear(128, 256) # todo: 优化4:增加网络层数、神经元个数 self.linear3 = nn.Linear(256, 512) self.linear4 = nn.Linear(512, 128) # 1.2.2 输出层 self.output = nn.Linear(128, output_dim) # 2. 前向传播 def forward(self, x): # 2.1 隐藏层: relu x = torch.relu(self.linear1(x)) x = torch.relu(self.linear2(x)) x = torch.relu(self.linear3(x)) x = torch.relu(self.linear4(x)) # 2.2 输出层: softmax # 这里不用写成softmax(x),因为nn.CrossEntropyLoss()里面已经包含了softmax() x = self.output(x) # 加权求和 return x # todo 3: 模型训练 def train(train_dataset, input_dim, output_dim): # 1. 获取数据加载器DataLoader # 参1: 数据集;参2: 批次大小;参数3: 是否打乱数据(训练集打乱,测试集不打乱) train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True) # 2. 创建模型 model = MobilePhonePriceClassification(input_dim, output_dim) # 3. 创建损失函数:多分类交叉熵损失函数 criterion = nn.CrossEntropyLoss() # 4. 创建优化器 # todo: 优化2: SGC 改为 Adam optimizer = optim.Adam(model.parameters(), lr=0.0001) # 5. 训练模型 # 5.1 训练轮数 # todo: 优化5: 增加训练轮数 epochs = 200 # 5.2 开始每轮的训练 for epoch in range(epochs): # 5.2.1 记录每次训练的损失值和批次数 total_loss, batch_num = 0.0, 0 # 5.2.2 记录训练开始的时间 start = time.time() # 5.2.3 开始本轮的各批次训练 for x, y in train_loader: # 5.2.3.1 切换模型(状态) model.train() # 训练模式 # 5.2.3.2 模型预测 y_pred = model(x) # 5.2.3.3 计算损失值 loss = criterion(y_pred, y) # 5.2.3.4 梯度清零,反向传播,优化参数 optimizer.zero_grad() loss.backward() optimizer.step() # 5.2.3.5 累计损失值和批次数 total_loss += loss.item() # 把本轮的每批次16条的平均损失值累加起来 batch_num += 1 # 5.2.4 本轮训练结束,打印训练信息 print(f'epoch: {epoch + 1}, loss: {total_loss / batch_num:.4f}, time: {time.time() - start:.2f}s') # 6. 此处多轮训练结束,保存模型(参数) # 参1: 模型参数信息;参2: 模型保存路径 torch.save(model.state_dict(), './model/mobile_phone_price_cls.pth') # todo 4: 模型测试 def evaluate(test_dataset, input_dim, output_dim): # 1. 创建神经网络分类对象 model = MobilePhonePriceClassification(input_dim, output_dim) # 2. 加载模型参数 model.load_state_dict(torch.load('./model/mobile_phone_price_cls.pth')) # 3. 创建数据加载器DataLoader test_loader = DataLoader(test_dataset, batch_size=16, shuffle=False) # 4. 记录预测正确的样本个数 correct = 0 # 5. 从数据加载器中获取每批次的数据 for x, y in test_loader: # 5.1 切换测试模式 model.eval() # 5.2 模型预测 y_pred = model(x) # print(f'y_pred: {y_pred}') # 加权求和的结果 # 5.3 根据加权求和,得到类别,用argmax()获取最大值对应的下标,即类别 y_pred = torch.argmax(y_pred, dim=1) print(f'预测类别:{y_pred}') # 如果值全都一样,可能是学习率太大了,调小试一下 # 5.4 统计预测正确的样本个数 correct += (y_pred == y).sum().item() # 6. 模型预测结束,计算准确率 print(f'准确率:{correct / len(test_dataset):.4f}') if __name__ == '__main__': # 1. 数据准备 train_dataset, test_dataset, input_dim, output_dim = load_data() # 2. 搭建神经网络 model = MobilePhonePriceClassification(input_dim, output_dim) # 2.1 计算模型参数 summary(model, input_size=(16, input_dim)) # input_size=(batch_size, input_dim), 每批16条,每条20个特征 # 3. 模型训练 train(train_dataset, input_dim, output_dim) # 4. 模型评估 evaluate(test_dataset, input_dim, output_dim)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/13 8:44:55

Linux上部署Samba AD域控:实现混合环境统一身份管理

1. 项目概述:为什么要在Linux上用Samba做域控? 在传统的企业IT架构里,提到“域控”(Domain Controller),大家的第一反应几乎都是微软的Windows Server。Active Directory(AD)几乎成了…

作者头像 李华
网站建设 2026/8/13 8:44:02

5分钟掌握开源安卓投屏神器:电脑无线控制手机的终极指南

5分钟掌握开源安卓投屏神器:电脑无线控制手机的终极指南 【免费下载链接】QtScrcpy Android real-time display control software 项目地址: https://gitcode.com/GitHub_Trending/qt/QtScrcpy 还在为手机屏幕太小而烦恼吗?想要在电脑上流畅操控安…

作者头像 李华
网站建设 2026/8/13 8:43:49

2026年数学建模国赛A题算法(13):边值问题的打靶法与差分法:从理论到工程应用的数学建模研究

摘要 边值问题(Boundary Value Problems, BVPs)是微分方程理论中的重要组成部分,广泛应用于物理学、工程学、生物学及经济学等领域。由于解析解的局限性,数值方法成为求解复杂边值问题的主要手段。本文系统研究了求解二阶常微分方程边值问题的两类核心数值方法——打靶法(…

作者头像 李华
网站建设 2026/8/13 8:43:41

2026年数学建模国赛A题算法(15):龙格-库塔法(RK4)与自适应步长求解:从经典到智能的常微分方程数值方法研究

摘要 常微分方程初值问题是科学计算与工程模拟中的核心课题,其数值求解方法的发展贯穿了计算数学的演进历程。本文系统研究了经典四阶龙格-库塔法(RK4)与自适应步长控制策略的理论基础、算法实现及性能特性。在回顾RK4方法的历史渊源与数学推导的基础上,本文深入分析了基于…

作者头像 李华
网站建设 2026/8/13 8:42:05

Python解析通达信.day二进制文件:金融数据本地化处理实战

1. 从数据孤岛到分析利器:一次通达信数据格式的深度解析 在金融数据分析和量化研究的圈子里,数据源永远是第一步,也是最关键的一步。很多朋友,尤其是刚开始接触Python进行股票分析的朋友,常常会卡在数据获取和预处理这…

作者头像 李华
网站建设 2026/8/13 8:41:52

Bash智能补全进阶:从原理到实战,提升命令行效率

1. 项目概述:为什么你需要一个更聪明的Bash如果你每天都在和Linux终端打交道,或者频繁使用macOS的Terminal,那你对Bash这个Shell一定不陌生。敲命令、写脚本、管理服务器,Bash几乎是每个开发者和运维工程师的“第二双手”。但不知…

作者头像 李华