ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

08-案例-手机价格分类

08-案例-手机价格分类 1. 需求分析小明创办了一家手机公司他不知道如何估算手机产品的价格。为了解决这个问题他收集了多家公司的手机销售数据。该数据为二手手机的各个性能的数据最后根据这些性能得到4个价格区间作为这些二手手机售出的价格区间。2. 数据说明数据来源手机价格分类_数据集-阿里云天池字段名字段说明battery_power电池一次可储存的总能量单位为毫安时blue是否有蓝牙clock_speed微处理器执行指令的速度dual_sim是否支持双卡fc前置摄像头百万像素four_g是否有 4Gint_memory内存GBm_dep移动深度cmmobile_wt手机重量n_cores处理器内核数pc主摄像头百万像素px_height像素分辨率高度px_width像素分辨率宽度ram随机存取存储器兆字节sc_h手机屏幕高度cmsc_w手机屏幕宽度cmtalk_time一次电池充电持续时间最长的时间three_g是否有 3Gtouch_screen是否有触控屏wifi是否能连 wifiprice_range价格区间01233. 建模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 summary3.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_size0.2, random_state11, stratifyy) # 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_dim3.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 x3.3 模型训练与保存网络编写完成之后需要编写训练函数。所谓的训练函数指的是输入数据读取、送入网络、计算损失、更新参数的流程该流程较为固定。我们使用的是多分类交叉生损失函数、使用 SGD 优化方法。最终将训练好的模型持久化到磁盘中。# todo 3: 模型训练 def train(train_dataset, input_dim, output_dim): # 1. 获取数据加载器DataLoader # 参1: 数据集参2: 批次大小参数3: 是否打乱数据训练集打乱测试集不打乱 train_loader DataLoader(train_dataset, batch_size16, shuffleTrue) # 2. 创建模型 model MobilePhonePriceClassification(input_dim, output_dim) # 3. 创建损失函数多分类交叉熵损失函数 criterion nn.CrossEntropyLoss() # 4. 创建优化器 optimizer optim.SGD(model.parameters(), lr0.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(fepoch: {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_size16, shuffleFalse) # 4. 记录预测正确的样本个数 correct 0 # 5. 从数据加载器中获取每批次的数据 for x, y in test_loader: # 5.1 切换测试模式 model.eval() # 5.2 模型预测 y_pred model(x) # print(fy_pred: {y_pred}) # 加权求和的结果 # 5.3 根据加权求和得到类别用argmax()获取最大值对应的下标即类别 y_pred torch.argmax(y_pred, dim1) 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. 不优化ACC0.585 1. 仅优化1ACC0.67 2. 仅优化2ACC0.71 3. 仅优化3ACC0.7975 4. 仅优化4ACC0.6825 5. 仅优化5ACC0.6450 6. 同时优化12345ACC0.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_size0.2, random_state11, stratifyy) # 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_size16, shuffleTrue) # 2. 创建模型 model MobilePhonePriceClassification(input_dim, output_dim) # 3. 创建损失函数多分类交叉熵损失函数 criterion nn.CrossEntropyLoss() # 4. 创建优化器 # todo: 优化2: SGC 改为 Adam optimizer optim.Adam(model.parameters(), lr0.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(fepoch: {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_size16, shuffleFalse) # 4. 记录预测正确的样本个数 correct 0 # 5. 从数据加载器中获取每批次的数据 for x, y in test_loader: # 5.1 切换测试模式 model.eval() # 5.2 模型预测 y_pred model(x) # print(fy_pred: {y_pred}) # 加权求和的结果 # 5.3 根据加权求和得到类别用argmax()获取最大值对应的下标即类别 y_pred torch.argmax(y_pred, dim1) 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)
返回列表