01-【深度学习】单车预测

源代码+数据下载地址
数据说明:

instant :序号(0-17379)
dteday :日期
season :季节
yr :两年的数量;0为2011年;1为2012年
mnth :月份
hr :每天小时
holiday :是否是节假日:1是;0否
weekday :周几
workingday :工作日:1是;0否
weathersit :
temp :
atemp :
hum :
windspeed :风速
casual :
registered :注册人数
cnt :单车使用数量

1、数据处理

1、读取数据

data_path = 'hour.csv'
rides = pd.read_csv(data_path, encoding='gbk') #加上encoding可以识别中文
# print(rides.head())

2、将类型变量转换为one-hot编码,变成多个属性

#对于类型变量的特殊处理
# season=1,2,3,4, weathersi=1,2,3, mnth= 1,2,...,12, hr=0,1, ...,23, weekday=0,1,...,6
# 经过下面的处理后,将会多出若干特征,例如,对于season变量就会有 season_1, season_2, season_3, season_4
# 这四种不同的特征。
dummy_fields = ['season', 'weathersit', 'mnth', 'hr', 'weekday']
for each in dummy_fields:
    #利用pandas对象,我们可以很方便地将一个类型变量属性进行one-hot编码,变成多个属性
    dummies = pd.get_dummies(rides[each], prefix=each, drop_first=False)
    rides = pd.concat([rides, dummies], axis=1)

# 把原有的类型变量对应的特征去掉,将一些不相关的特征去掉
fields_to_drop = ['instant', 'dteday', 'season', 'weathersit',
                  'weekday', 'atemp', 'mnth', 'workingday', 'hr']
data = rides.drop(fields_to_drop, axis=1)

3、将数值变量进行归一化处理

# 调整所有的特征,标准化处理
quant_features = ['cnt', 'temp', 'hum', 'windspeed']
#quant_features = ['temp', 'hum', 'windspeed']

# 我们将每一个变量的均值和方差都存储到scaled_features变量中。
scaled_features = {}
for each in quant_features:
    mean, std = data[each].mean(), data[each].std()
    scaled_features[each] = [mean, std]
    data.loc[:, each] = (data[each] - mean)/std
# print(data['temp'][0])
print(rides['temp'][:10])

4、划分数据集为训练数据和测试数据

# 将所有的数据集分为测试集和训练集,我们以后21天数据一共21*24个数据点作为测试集,其它是训练集
test_data = data[-21*24:]
train_data = data[:-21*24]
# print('训练数据:',len(train_data),'测试数据:',len(test_data))

# 将我们的数据列分为特征列和目标列

#目标列
target_fields = ['cnt', 'casual', 'registered']
features, targets = train_data.drop(target_fields, axis=1), train_data[target_fields]
test_features, test_targets = test_data.drop(target_fields, axis=1), test_data[target_fields]

# 将数据从pandas dataframe转换为numpy
X = features.values
Y = targets['cnt'].values
Y = Y.astype(float)

Y = np.reshape(Y, [len(Y),1])

2、搭建网络模型

网络介绍:我们这里有需要输入的数据有n个,我们要么计算出需要输入的个数,要么可以通过下面直接得出输入数据个数

target_fields = ['cnt', 'casual', 'registered']
features, targets = train_data.drop(target_fields, axis=1), train_data[target_fields]
input_size = features.shape[1]  # 输入层单元个数

我们的隐藏单元数为:10

输出单元个数:1 (我们只要预测单车的数量即可)

1、自定义网络网络搭建

# 定义神经网络架构,features.shape[1]个输入层单元,10个隐含层,1个输出层
input_size = features.shape[1]  # 输入层单元个数
hidden_size = 10  # 隐含层单元个数
output_size = 1  # 输出层单元个数
batch_size = 128  # 每隔batch的记录数
weights1 = torch.randn([input_size, hidden_size], dtype=torch.double, requires_grad=True)  # 第一到二层权重
biases1 = torch.randn([hidden_size], dtype=torch.double, requires_grad=True)  # 隐含层偏置
weights2 = torch.randn([hidden_size, output_size], dtype=torch.double, requires_grad=True)  # 隐含层到输出层权重


def neu(x):
    # 计算隐含层输出
    # x为batch_size * input_size的矩阵,weights1为input_size*hidden_size矩阵,
    # biases为hidden_size向量,输出为batch_size * hidden_size矩阵
    hidden = x.mm(weights1) + biases1.expand(x.size()[0], hidden_size)
    hidden = torch.sigmoid(hidden)

    # 输入batch_size * hidden_size矩阵,mm上weights2, hidden_size*output_size矩阵,
    # 输出batch_size*output_size矩阵
    output = hidden.mm(weights2)
    return output


def cost(x, y):
    # 计算损失函数
    error = torch.mean((x - y) ** 2)
    return error


def zero_grad():
    # 清空每个参数的梯度信息
    if weights1.grad is not None and biases1.grad is not None and weights2.grad is not None:
        weights1.grad.data.zero_()
        weights2.grad.data.zero_()
        biases1.grad.data.zero_()


def optimizer_step(learning_rate):
    # 梯度下降算法
    weights1.data.add_(- learning_rate * weights1.grad.data)
    weights2.data.add_(- learning_rate * weights2.grad.data)
    biases1.data.add_(- learning_rate * biases1.grad.data)

网络训练

# 神经网络训练循环
losses = []
for i in range(1000):
    # 每128个样本点被划分为一个撮,在循环的时候一批一批地读取
    batch_loss = []
    # start和end分别是提取一个batch数据的起始和终止下标
    for start in range(0, len(X), batch_size):
        end = start + batch_size if start + batch_size < len(X) else len(X)
        xx = torch.tensor(X[start:end], dtype=torch.double, requires_grad=True)
        yy = torch.tensor(Y[start:end], dtype=torch.double, requires_grad=True)
        predict = neu(xx)
        loss = cost(predict, yy)
        zero_grad()
        loss.backward()
        optimizer_step(0.01)
        batch_loss.append(loss.data.numpy())

    # 每隔100步输出一下损失值(loss)
    if i % 100 == 0:
        losses.append(np.mean(batch_loss))
        print(i, np.mean(batch_loss))

    #保存网络模型
    if(i == 9999):
        torch.save(neu, "自定义网络参数(模型+参数).pth")
        torch.save(neu.state_dict(), "自定义网络参数(参数).pth")

2、直接调库网络搭建

# 定义神经网络架构,features.shape[1]个输入层单元,10个隐含层,1个输出层
input_size = features.shape[1]
hidden_size = 10
output_size = 1
batch_size = 128
neu = torch.nn.Sequential(
    torch.nn.Linear(input_size, hidden_size),
    torch.nn.Sigmoid(),
    torch.nn.Linear(hidden_size, output_size),
)
cost = torch.nn.MSELoss()
optimizer = torch.optim.SGD(neu.parameters(), lr = 0.01)

网络训练

# 神经网络训练循环
losses = []
for i in range(1000):
    # 每128个样本点被划分为一个撮,在循环的时候一批一批地读取
    batch_loss = []
    # start和end分别是提取一个batch数据的起始和终止下标
    for start in range(0, len(X), batch_size):
        end = start + batch_size if start + batch_size < len(X) else len(X)
        xx = torch.tensor(X[start:end], dtype=torch.float, requires_grad=True)
        yy = torch.tensor(Y[start:end], dtype=torch.float, requires_grad=True)
        predict = neu(xx)
        loss = cost(predict, yy)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        batch_loss.append(loss.data.numpy())

    # 每隔100步输出一下损失值(loss)
    if i % 100 == 0:
        losses.append(np.mean(batch_loss))
        print(i, np.mean(batch_loss))
    if i==999:
        torch.save(neu, "单车预测(调库版)-(模型+参数).pth")
        torch.save(neu.state_dict(), "单车预测(调库版)-(参数).pth")

3、结果测试

# 用训练好的神经网络在测试集上进行预测
targets = test_targets['cnt'] #读取测试集的cnt数值
targets = targets.values.reshape([len(targets),1]) #将数据转换成合适的tensor形式
targets = targets.astype(float) #保证数据为实数

x = torch.tensor(test_features.values, dtype = torch.float, requires_grad = True)
y = torch.tensor(targets, dtype = torch.float, requires_grad = True)

print(x[:10])
# 用神经网络进行预测
predict = neu(x)
predict = predict.data.numpy()

print((predict * std + mean)[:10])

4、结果出图展示

# 将后21天的预测数据与真实数据画在一起并比较
# 横坐标轴是不同的日期,纵坐标轴是预测或者真实数据的值
fig, ax = plt.subplots(figsize = (10, 7))

mean, std = scaled_features['cnt']
ax.plot(predict * std + mean, label='Prediction', linestyle = '--')
ax.plot(targets * std + mean, label='Data', linestyle = '-')
ax.legend()
ax.set_xlabel('Date-time')
ax.set_ylabel('Counts')
# 对横坐标轴进行标注
dates = pd.to_datetime(rides.loc[test_data.index]['dteday'])
dates = dates.apply(lambda d: d.strftime('%b %d'))
ax.set_xticks(np.arange(len(dates))[12::24])
_ = ax.set_xticklabels(dates[12::24], rotation=45)

plt.show()

5、训练好的网络直接调用

只针对调库搭建的网络,还是需要将数据进行预处理的,但是不再需要训练网络

1、保存模型和数据

model = torch.load("单车预测(调库版)-(模型+参数).pth")
print(model)
predict = model(x)
predict = predict.data.numpy()

2、只保留数据,没有保留网络模型的

需要定义网络模型

# 定义神经网络架构,features.shape[1]个输入层单元,10个隐含层,1个输出层
input_size = features.shape[1]
hidden_size = 10
output_size = 1
batch_size = 128
neu = torch.nn.Sequential(
    torch.nn.Linear(input_size, hidden_size),
    torch.nn.Sigmoid(),
    torch.nn.Linear(hidden_size, output_size),
)

读取网络训练参数

neu.load_state_dict(torch.load("单车预测(调库版)-(参数).pth"))
print(neu)
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值