人工神经网络项目实战:价格分类案例
我们需要帮助小明找出手机的功能(例如:RAM等)与其售价之间的某种关系。我们可以使用机器学习的方法来解决这个问题,也可以构建一个全连接的网络。小明创办了一家手机公司,他不知道如何估算手机产品的价格。为了解决这个问题,他收集了多家公司的手机销售数据。该数据为二手手机的各个性能的数据,最后根据这些性能得到。4个价格区间,作为这些二手手机售出的价格区间。,所以该问题也是一个。
·
需求分析:
小明创办了一家手机公司,他不知道如何估算手机产品的价格。为了解决这个问题,他收集了多家公司的手机销售数据。该数据为二手手机的各个性能的数据,最后根据这些性能得到4个价格区间,作为这些二手手机售出的价格区间。
我们需要帮助小明找出手机的功能(例如:RAM等)与其售价之间的某种关系。我们可以使用机器学习的方法来解决这个问题,也可以构建一个全连接的网络。
需要注意的是: 在这个问题中,我们不需要预测实际价格,而是一个价格范围,它的范围使用 0、1、2、3 来表示,所以该问题也是一个分类问题。接下来我们还是按照四个步骤来完成这个任务:
- l准备训练集数据
- l构建要使用的模型
- l模型训练
- l模型预测评估
- 数据字段如下:

主要分为4个部分:
1:处理数据
# 1.自定义处理数据的api,batch_size是每批次的数据数量 def get_data(phone_path, batch_size): # 1.1 读取数据 data = pd.read_csv(phone_path) # 1.2 了解数据 print(data.shape) # 1.3 处理数据 # 先分别获取x特征,y标签 x = data.iloc[:, :-1].astype(np.float32) y = data.iloc[:, -1].astype(np.int64) # 然后使用train_test_split切割数据 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=666) # 最后封装TensorDataset train_dataset = TensorDataset(torch.from_numpy(x_train.values), torch.tensor(y_train.values)) test_dataset = TensorDataset(torch.from_numpy(x_test.values), torch.tensor(y_test.values)) # 1.4 封装dataloader数据加载器,shuffle=True是开启自动打乱数据, train_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) test_dataloader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False) # 1.5 获取输入特征数和输出类别数(去重),x_train[0][1]分别是行和列数 input_nums = x_train.shape[1] output_nums = len(y_train.unique()) # TODO 返回结果 return train_dataloader, test_dataloader, input_nums, output_nums2:构建模型
# 2.自定义模型 class PhonePriceModel(torch.nn.Module): # 重写init方法,input_nums:特征数量 output_nums:类别数量 def __init__(self, input_nums, output_nums): # 调用父类初始化方法 super().__init__() # 定义网络结构 self.linear1 = torch.nn.Linear(input_nums, 128) self.linear2 = torch.nn.Linear(128, 256) self.out = torch.nn.Linear(256, output_nums) # 重写forward def forward(self, x): # 前向传播(加权求和->激活函数) x = torch.relu(self.linear1(x)) x = torch.relu(self.linear2(x)) # TODO 注意: 本次项目是多分类项目,后续要使用多分类交叉熵损失函数,所以此处不使用softmax激活函数 x = self.out(x) return x3:模型训练
# 3.模型训练 def model_train(train_dataloader, model, epochs, model_path): # todo 1.准备数据(已经传参) # todo 2.准备模型(已经传参) # todo 3.准备损失函数 loss_fn = torch.nn.CrossEntropyLoss() # todo 4.准备优化器 optimizer = torch.optim.SGD(model.parameters(), lr=0.01) # todo 5.训练模型 # 5.1 遍历轮次 for epoch in range(epochs): # 提前定义变量用于存储总损失,批次次数,时间 total_loss, batch_cnt, start_time = 0.0, 0, time.time() # 5.2 遍历训练数据 for batch_x, batch_y in train_dataloader: # todo 前向传播 # 获取预测数据 logits = model(batch_x) # 计算损失 loss = loss_fn(logits, batch_y) # 底层先用softmax转概率,再计算交叉熵损失 # 累计损失和批次次数 total_loss += loss.item() batch_cnt += 1 # todo 反向传播 # 梯度清零 optimizer.zero_grad() # 计算梯度 loss.backward() # 参数更新 optimizer.step() epoch_loss = total_loss / batch_cnt print(f"第{epoch + 1}轮,最新损失为:{epoch_loss},耗时:{time.time() - start_time}") # todo 模型保存 torch.save(model.state_dict(), model_path)4:模型评估
def model_evaluate(input_nums, output_nums, model_path, test_dataloader): # 1.创建空模型并加载训练好的模型参数 model = PhonePriceModel(input_nums, output_nums) model.load_state_dict(torch.load(model_path)) # 2.设置模型评估模式 model.eval() # 3.模型预测 correct_nums = 0 for batch_x, batch_y in test_dataloader: # 前向传播 logits = model(batch_x) # 获取预测结果,获取得分最高的类别索引,得分最高的类别即是预测的类别 pred = torch.argmax(logits, dim=1) # 计算正确数量 correct_nums += (pred == batch_y).sum() # 4.todo 计算准确率 print(f"准确率:{correct_nums / len(test_dataloader.dataset)}")
主函数:
if __name__ == '__main__':
# TODO 1.处理数据
phone_path = "data/手机价格预测.csv"
batch_size = 20
# 调用get_data()
train_dataloader, test_dataloader, input_nums, output_nums = get_data(phone_path, batch_size)
print(
f"训练批次数:{len(train_dataloader)},数据{len(train_dataloader.dataset)};测试批次数:{len(test_dataloader)},数据{len(test_dataloader.dataset)};输入特征数:{input_nums},输出类别数:{output_nums}")
# TODO 2.构建模型
model = PhonePriceModel(input_nums, output_nums)
# TODO 3.模型训练
epochs = 50
model_path = "model/PhoneModel.pth"
model_train(train_dataloader, model, epochs, model_path)
# TODO 4.模型评估
model_evaluate(input_nums, output_nums, model_path, test_dataloader)
贴上一个简单优化版本
# 导包
import time
import pandas as pd
import numpy as np
import torch
from sklearn.model_selection import train_test_split
from torch.utils.data import TensorDataset, DataLoader
# 1.自定义处理数据的api
def get_data(phone_path, batch_size):
# 1.1 读取数据
data = pd.read_csv(phone_path)
# 1.2 了解数据
print(data.shape)
# 1.3 处理数据
# 先分别获取x特征,y标签
x = data.iloc[:, :-1].astype(np.float32)
y = data.iloc[:, -1].astype(np.int64)
# 然后使用train_test_split切割数据
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=88)
# 最后封装TensorDataset
train_dataset = TensorDataset(torch.from_numpy(x_train.values), torch.tensor(y_train.values))
test_dataset = TensorDataset(torch.from_numpy(x_test.values), torch.tensor(y_test.values))
# 1.4 封装dataloader数据加载器
train_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_dataloader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
# 1.5 获取输入特征数和输出类别数(去重)
input_nums = x_train.shape[1]
output_nums = len(y_train.unique())
# TODO 返回结果
return train_dataloader, test_dataloader, input_nums, output_nums
# 2.自定义模型
class PhonePriceModel(torch.nn.Module):
# 重写init方法
def __init__(self, input_nums, output_nums):
# 调用父类初始化方法
super().__init__()
# 定义网络结构
self.linear1 = torch.nn.Linear(input_nums, 128)
self.linear2 = torch.nn.Linear(128, 256)
self.linear3 = torch.nn.Linear(256, 256)
self.linear4 = torch.nn.Linear(256, 256)
self.linear5 = torch.nn.Linear(256, 256)
self.out = torch.nn.Linear(256, output_nums)
# 重写forward
def forward(self, x):
# 前向传播(加权求和->激活函数)
x = torch.relu(self.linear1(x))
x = torch.relu(self.linear2(x))
x = torch.relu(self.linear3(x))
x = torch.relu(self.linear4(x))
x = torch.relu(self.linear5(x))
# TODO 注意: 本次项目是多分类项目,后续要使用多分类交叉熵损失函数,所以此处不使用softmax激活函数
x = self.out(x)
return x
# 3.模型训练
def model_train(train_dataloader, model, epochs, model_path):
# todo 1.准备数据(已经传参)
# todo 2.准备模型(已经传参)
# todo 3.准备损失函数
loss_fn = torch.nn.CrossEntropyLoss()
# todo 4.准备优化器
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# todo 5.训练模型
# 5.1 遍历轮次
for epoch in range(epochs):
# 提前定义变量用于存储总损失,批次次数,时间
total_loss, batch_cnt, start_time = 0.0, 0, time.time()
# 5.2 遍历训练数据
for batch_x, batch_y in train_dataloader:
# todo 前向传播
# 获取预测数据
logits = model(batch_x)
# 计算损失
loss = loss_fn(logits, batch_y) # 底层先用softmax转概率,再计算交叉熵损失
# 累计损失和批次次数
total_loss += loss.item()
batch_cnt += 1
# todo 反向传播
# 梯度清零
optimizer.zero_grad()
# 计算梯度
loss.backward()
# 参数更新
optimizer.step()
epoch_loss = total_loss / batch_cnt
print(f"第{epoch + 1}轮,最新损失为:{epoch_loss},耗时:{time.time() - start_time}")
# todo 模型保存
torch.save(model.state_dict(), model_path)
# 4.模型评估
def model_evaluate(input_nums, output_nums, model_path, test_dataloader):
# 1.创建空模型并加载训练好的模型参数
model = PhonePriceModel(input_nums, output_nums)
model.load_state_dict(torch.load(model_path))
# 2.设置模型评估模式
model.eval()
# 3.模型预测
correct_nums = 0
for batch_x, batch_y in test_dataloader:
# 前向传播
logits = model(batch_x)
# 获取预测结果
pred = torch.argmax(logits,dim=1)
# 计算正确数量
correct_nums += (pred == batch_y).sum()
# 4.todo 计算准确率
print(f"准确率:{correct_nums / len(test_dataloader.dataset)}")
if __name__ == '__main__':
# TODO 1.处理数据
phone_path = "data/手机价格预测.csv"
batch_size = 16
# 调用get_data()
train_dataloader, test_dataloader, input_nums, output_nums = get_data(phone_path, batch_size)
print(f"训练批次数:{len(train_dataloader)},数据{len(train_dataloader.dataset)};测试批次数:{len(test_dataloader)},数据{len(test_dataloader.dataset)};输入特征数:{input_nums},输出类别数:{output_nums}")
# TODO 2.构建模型
model = PhonePriceModel(input_nums, output_nums)
# TODO 3.模型训练
epochs = 200
model_path = "model/PhoneModel.pth"
model_train(train_dataloader, model, epochs, model_path)
# TODO 4.模型评估
model_evaluate(input_nums, output_nums, model_path, test_dataloader)
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)