pytorch实战

本文介绍了PyTorch中的张量概念,包括向量、矩阵及其操作。讲解了如何在GPU上进行运算,以及动态计算图的概念和自动微分机制。通过房价预测的例子展示了反向传播和梯度更新。此外,讨论了单车预测器的过拟合问题,以及数据预处理中的one-hot编码和数值变量标准化。最后,提到了神经网络在分类问题中的应用。
部署运行你感兴趣的模型镜像

1、简介

1.1张量的定义与访问

pytorch的运算单元称为张量tensor,一维张量称为向量vector,二维张量称为矩阵matrix

张量的维度大小称为这个维度的尺寸size,矩阵的size就是2

x=torch.rand(5,3) # [0,1]区间的值
y=torch.ones(5,3) #全1的值
z=torch.zeros(2,5,3) #全0的值

x[1,2] #下标从0开始,这是访问,2行第三个
x[:,3]# 切片,访问第4列全部

q=x.mm(y.t()) #mm(matrix multiply)矩阵乘法,y.t()转置

tensor与numpy可以相互转化

x=torch.rand(5,3) 
y = x.numpy()

>>array([[0.51880044, 0.2535311 , 0.21637958],
       [0.8806777 , 0.39265507, 0.10351849],
       [0.59132063, 0.527045  , 0.5983402 ],
       [0.9838265 , 0.45807636, 0.18984991],
       [0.5437703 , 0.7144072 , 0.12551159]], dtype=float32)

z=torch.FloatTensor(y) #将numpy数组转为tensor,顺带强制类型转换为float,同理inttensor,longtensor

1.2使用GPU进行运算

x=torch.rand(5,3) # [0,1]区间的值
y=torch.ones(5,3) #全1的值

x=x.cuda()
y=y.cuda()
print(x+y)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5n4S3Kom-1688608374300)(C:\Users\psa\AppData\Roaming\Typora\typora-user-images\image-20230616213907124.png)]

device='cuda:0'表明输出存储在了GPU

1.3动态计算图

计算图:记录计算过程的图,方框表示变量,椭圆表示运算操作,箭头标明运算进行方向

自动微分变量,torch 1.5以后和tensor合并,但是任然支持自动微分变量

采用自动微分变量之后,每进行一个运算之后,系统都会自动构造一个计算图来记录所有的计算过程,在构建好动态计算图后,我们可以利用.backward()函数自动执行反向传播算法,从而计算每一个自动微分变量的梯度信息

pytorch 规定不能直接对自动微分变量进行数值更新,只能对其data进行更新,

pytorch 中,如果一个函数后面加了’_'表明函数的运算结果直接存到当前变量中去

自动微分变量有三个重要属性:

  • data 存储计算结果
  • grad_fn 计算的上一个节点
  • grad,调用.backward()函数,会计算所有变量的梯度信息,并将叶节点的导数值存在.grad中
实例
x=torch.ones(2,2,requires_grad=True) #自动微分变量,其与tensor的唯一区别就是requires_grad=True
y = torch.rand(2,2,requires_grad=True)
x=x+y
x.grad_fn #上一节点

可视化计算图好像要import别的东西

用于求导数,只有叶节点才能计算grad信息

房价预测

matplotlib.pyplot的plot函数

  1. plt.plot(x,y)函它可以绘制点和线, 并且对其样式进行控制. x为x轴数据, y为y轴数据

  2. plt.plot(x, y, “格式控制字符串”),点和线的格式可以用"格式控制字符串"设置plt.plot(x,y,“ob:”) --"b"为蓝色, "o"为圆点, ":"为点线,默认为实线; "格式控制字符串"最多可以包括三部分, “颜色”, “点型”, “线型”

color=['b','g','r','c','m','y','k','w']
linestyle=['-','--','-.',':']

":“点线,”-."点画线, "–"短划线, "-"实线

#准备数据
x = torch.linspace(0,100,100).type(torch.FloatTensor)# linspace生成0-100的100个间隔均匀的数据
rand = torch.randn(100)*10
y=x+rand #历史房价数据y
x_train=x[:-10] #取倒数第十个数据作为训练数据
x_test=x[-10:] #取最后十个数据作为测试数据
y_train=y[:-10]
y_test=y[-10:]

import matplotlib.pyplot as plt #导入画图的程序包
plt.figure(figsize=(10,8))
plt.plot(x_train.data.numpy(),y_train.data.numpy(),'o')
plt.xlabel('X')#添加x轴的标注
plt.ylabel('Y')#添加y轴的标注
plt.show()

#训练
a = torch.rand(1,requires_grad=True)
b = torch.rand(1,requires_grad=True)
learning_rate = 0.0001 #学习率,调节更新的快慢,越大越快,可能越更加不准确
#进行迭代计算
for i in range(1000):
    #将所有训练数据带入模型ax+b,计算预测值
    predictions = a.expand_as(x_train)*x_train +b.expand_as(x_train)#expand_as,将a扩展为和x_train一样的维度
    loss = torch.mean((predictions-y_train)**2)#predictions 和 标签值进行比较,得出损失函数
    print('loss:',loss)
    loss.backward()#对损失函数进行梯度反传
    #利用得到的梯度信息更新a中的data
    a.data.add_(- learning_rate * a.grad.data)#a.add_会把结果直接存入a
    b.data.add_(- learning_rate * b.grad.data)
    #清除a,b中的梯度信息,防止重复叠加
    a.grad.data.zero_()
    b.grad.data.zero_()
    
    #显示
x_data = x_train.data.numpy()
plt.figure(figsize=(10,7)) #定义窗口大小
xplot, =plt.plot(x_data,y_train.data.numpy(),'o') #绘制x,y的散点图
yplot, =plt.plot(x_data,a.data.numpy()*x_data + b.data.numpy())#绘制拟合的直线
plt.xlabel("X")#添加标注
plt.ylabel('Y')
str1 = str(a.data.numpy()[0]) + 'x +' + str(b.data.numpy()[0]) #将拟合直线的ab显示出来
plt.legend([xplot,yplot],['Data',str1])#显示左上角的两个东西
plt.show()

#预测
x_data = x_train.data.numpy() # 获得x包裹的数据
x_pred = x_test.data.numpy()
plt.figure(figsize = (10, 7)) #设定绘图窗口大小
plt.plot(x_data, y_train.data.numpy(), 'o') # 绘制训练数据
plt.plot(x_pred, y_test.data.numpy(), 's') # 绘制测试数据
x_data = np.r_[x_data, x_test.data.numpy()]
plt.plot(x_data, a.data.numpy() * x_data + b.data.numpy())  #绘制拟合数据
plt.plot(x_pred, a.data.numpy() * x_pred + b.data.numpy(), 'o') #绘制预测数据
plt.xlabel('X') #更改坐标轴标注
plt.ylabel('Y') #更改坐标轴标注
str1 = str(a.data.numpy()[0]) + 'x +' + str(b.data.numpy()[0]) #图例信息
plt.legend([xplot, yplot],['Data', str1]) #绘制图例
plt.show()

image-20230617215126669 image-20230625134722482

2、单车预测器

单车预测器1.0–过拟合

#导入模块
import numpy as np
import pandas as pd
import torch
import torch.optim as optim
import matplotlib.pyplot as plt
#直接显示输出图像,不需要show
%matplotlib inline 

#导入数据
data_path = 'C:/Users/psa/Desktop/MarkDown学习记录/pytorch实战源码/book_DeepLearning_in_PyTorch_Source-master/03_bike_predictor/bike-sharing-dataset/hour.csv'
rides = pd.read_csv(data_path)#读取数据
rides.head()
counts = rides['cnt'][:50]#取cnt字段的前50
x = np.arange(len(counts))
y = np.array(counts)
plt.figure(figsize = (10,7))
plt.plot(x,y,'o-')


#设置神经网络初始参数
#数据样本
x = torch.FloatTensor(np.arange(len(counts),dtype=float))/ len(counts)#输入变量,除len(counts)-->归一化处理,让输入数据的范围限制在(0,1),减小数据范围,加快计算速度,相同时间内拟合的曲线变得更好
y = torch.FloatTensor(np.array(counts,dtype=float)) #输出变量

sz = 10 #隐含神经元的数量
#初始化输入层到隐层的权值矩阵,size=(1,10)
weights = torch.randn((1,sz),requires_grad = True)
#设置隐层阶段的偏移b,他是size=10的一维向量
biases = torch.randn((sz),requires_grad=True)
#初始化隐层到输出层的权值矩阵,size=(10,1)
weight2 = torch.randn((sz,1),requires_grad=True)


#迭代训练神经网络
learning_rate = 0.001 #设置学习率
losses = []#记录每一次迭代的损失函数
x = x.view(50,-1)#在pytorch中的view()函数就是用来改变tensor的形状的,其中-1表示会自适应的调整剩余的维度
y = y.view(50,-1)
for i in range(100000):
    #输入层到隐层的计算
    hidden = x*weights + biases#size of hideen is (50,10),50个数据点,10个神经元
    
    #将sigmoid函数应用在隐层的每一个神经元上
    hidden = torch.sigmoid(hidden)
    
    #从隐层输出到输出层
    predictions = hidden.mm(weight2)#predictions 的size是(50,1),即50个数据点的预测值

    #prediction与标准答案y进行比较,计算均方差
    loss = torch.mean((predictions - y )**2)
    #将loss加入损失数组
    losses.append(loss.data.numpy())

    #每隔10000个周期打印一下损失函数数值
    if i % 10000 == 0:
        print('loss:',loss)
    
    #***************************************
    #梯度下降算法,将误差反向运算
    loss.backward() #计算梯度(导数)

    #利用旧的w,b等梯度信息更新weight,biases,学习率*旧值
    weights.data.add_(- learning_rate*weights.grad.data)
    biases.data.add_(- learning_rate*biases.grad.data)
    weight2.data.add_(- learning_rate*weight2.grad.data)

    #清空所有梯度值
    weights.grad.data.zero_()
    biases.grad.data.zero_()
    weight2.grad.data.zero_()

    
#模型的损失函数loss曲线
plt.plot(losses)
plt.xlabel('Epoch')
plt.ylabel('Loss')

#预测输出的曲线和实际值进行对比
x_data = x.data.numpy()
plt.figure(figsize=(10,7)) #设定绘图窗口大小
xplot, = plt.plot(x_data,y.data.numpy(),'o')
yplot, = plt.plot(x_data,predictions.data.numpy())

plt.legend([xplot,yplot],['Data','predictions under 1000000 epochs'])


#进行预测
counts_predict = rides['cnt'][50:100] #读取待预测的接下来的50个数据点

#首先对接下来的50个数据点进行选取,注意x应该取51,52,……,100,然后再归一化
x = torch.FloatTensor((np.arange(50, 100, dtype = float) / len(counts)))
#读取下50个点的y数值,不需要做归一化
y = torch.FloatTensor(np.array(counts_predict, dtype = float))

x = x.view(50, -1)
y = y.view(50, -1)

# 从输入层到隐含层的计算
hidden = x * weights + biases

# 将sigmoid函数作用在隐含层的每一个神经元上
hidden = torch.sigmoid(hidden)

# 隐含层输出到输出层,计算得到最终预测
predictions = hidden.mm(weight2)

# 计算预测数据上的损失函数
loss = torch.mean((predictions - y) ** 2) 
print(loss)


x_data = x.data.numpy() # 获得x包裹的数据
plt.figure(figsize = (10, 7)) #设定绘图窗口大小
xplot, = plt.plot(x_data, y.data.numpy(), 'o') # 绘制原始数据
yplot, = plt.plot(x_data, predictions.data.numpy())  #绘制拟合数据
plt.xlabel('X') #更改坐标轴标注
plt.ylabel('Y') #更改坐标轴标注
plt.legend([xplot, yplot],['Data', 'Prediction']) #绘制图例
plt.show()
#发现过拟合,

分析:选取的特征变量是下标,下标显然与单车的数量没有关系

单车预测器2.0–人工神经网络Neu

1、数据预处理

我们将数据划分成了不同的撮(batch),一个批次一个批次地训练神经网络,因此我们要对数据进行划分。

这个样本的数据类型:

  • 类型变量:用数字代表变量,天气:1晴天,2多云,3小雨
  • 数值类型:在一个数值区间中去连续值
1.1、类型变量的one-hot编码

有很多变量都属于类型变量,例如season=1,2,3,4,分四季。我们不能将season变量直接输入到神经网络,这是因为season数值越高并不表示相应的信号强度越大。我们的解决方案是将类型变量用一个“一位热码“(one-hot)来编码,也就是:

season = 1 --> (1,0,0,0) season = 2 -->(0,1,0,0)

因此,如果一个类型变量有n个不同取值,那么one-hot向量长度就为n

pd.getdummies(data,...):#进行one-hot编码
prefix:str, list of str,dict of str, 默认为 None
用于追加DataFrame列名称的字符串。
 
prefix_sep:str, 默认为 ‘_’
如果附加前缀,则使用分隔符/分隔符。或者像这样传递列表或字典prefix。
 
dummy_na:bool, 默认为 False
如果忽略False NaN。
 
columns:list-like, 默认为 None
要编码的DataFrame中的列名。如果columns为None,则所有具有的列object或者categorydtype将被转换。
 
sparse:bool, 默认为 False
dummy-encoded列是否应由a支持SparseArray(True)或常规NumPy数组(False)。
 
drop_first:bool, 默认为 False
是否通过删除第一个级别从k个分类级别中获取k-1个虚拟对象。
1.2、数值类型变量的处理

减均值除标准差

temp′=temp−mean(temp)std(temp) temp'=\frac{temp-mean(temp)}{std(temp)} temp=std(temp)tempmean(temp)
可以将不同的取值范围的变量设置为让它们处于一个平等的地位

1.3、数据集划分

划分训练集和数据集

划分前16875条数据为训练数据,后21天的数据504条为测试数据

type() 返回参数的数据类型

dtype 返回数组中元素的数据类型

astype() 对数据类型进行转换

2、构建神经网络

1、搭建神经网络

  • 自己手动创建人工神经网络
  • 通过pytorch的sequential函数创建人工神经网络

2、数据的批处理

将所以数据按批次大小(batch size)划分为若干个批次

# expand()函数只能将size=1的维度扩展到更大的尺寸,如果扩展其他size()的维度会报错。

import torch
x = torch.tensor(3,2,1)
x.size()[0]#最外层维度:3
x.size()[1]#output:2
x.size()[2]#1
import pandas as pd
import numpy as np
import torch
import torch.optim as optim
import matplotlib.pyplot as plt


#导入数据
data_path = 'C:/Users/psa/Desktop/MarkDown学习记录/pytorch实战源码/book_DeepLearning_in_PyTorch_Source-master/03_bike_predictor/bike-sharing-dataset/hour.csv'
rides = pd.read_csv(data_path)
rides.head()


#处理类型变量
dummy_fields = ['season','weathersit','mnth','hr','weekday']
for each in dummy_fields:
    dummies = pd.get_dummies(rides[each],prefix=each,drop_first=False)#变为onehot编码
    rides = pd.concat([rides,dummies],axis=1)#合并,riedes里面是列名

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


#处理数值类型变量
quant_features = ['cnt', 'temp', 'hum', 'windspeed']
scaled_feature = {}
for each in quant_features:
    mean, std = data[each].mean() , data[each].std()#对当前feature的mean和std赋值
    scaled_feature[each] = [mean,std]
    data.loc[:,each] = (data[each] - mean) / std#减均值除标准差
    
    
    
#划分数据集
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]
X = features.values.astype(float)#x是特征列的值
Y = targets['cnt'].values#y为什么只要用户数,临时用户casual不考虑吗
Y = Y.astype(float)
Y = np.reshape(Y, [len(Y),1])
losses = []


#使用pytorch生成人工神经网络
#定义输入层,隐层,输出层的尺寸
input_size = features.shape[1]
hidden_size = 10
output_size = 1
batch_size = 128
neu = torch.nn.Sequential(#Sequential函数将一系列的运算模块按顺序搭建成神经网络,
    torch.nn.Linear(input_size,hidden_size),#输入层到隐层的映射,线性
    torch.nn.Sigmoid(),#对隐层,sigmoid
    torch.nn.Linear(hidden_size,output_size),#隐层到输出层的线性变换
)
cost = torch.nn.MSELoss()#MSELoss用来计算预测值x和目标值的均方误差,通过cost(x,y)来调用

optimizer = torch.optim.SGD(neu.parameters(),lr=0.01)#torch.optim.SGD调用了pytorch自带的梯度下降算法SGD(stochastic gradient descent)
#neu.parameters里包含了neu的所有权重w和偏置b,lr是设置的学习率
 
    

#分批训练数据 batch_size = 128
losses = []
for i in range(1000):
    batch_loss = []
    #对每个batch进行训练
    for start in range(0,len(X),batch_size):#range(start,stop,step_len)
    #我认为batch_size用来做step的话批次大小就不是128了,batch_size应该变成了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))

fig = plt.figure(figsize=(10,7))
plt.plot(np.arange(len(losses))*100,losses,'o-')   
plt.xlabel('epoch')#每100个ilosses添加一个元素,每个i一次epoch,所以losses*100是epoch
plt.ylabel('MSE')#MSE均方误差,用来描述预测值与实际值的差距


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

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


# 用神经网络进行预测
predict = neu(x)
predict = predict.data.numpy()


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

mean, std = scaled_feature['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)




3、中文情绪分类器–分类神经网络

分类神经网络

输入神经元与特征变量的数量相同

输出神经元的数量与所求的结果数量相同

最后只输出一个分类结果

要求所有的输出值之和为1,对其输出层后面加一个softmax层。

损失函数使用交叉熵函数

torch.nn.functional.softmax(x,dim=1)#softmax

#交叉熵
func = torch.nn.LogSoftmax(dim=1)
y = func(x)
L = torch.nn.NLLLoss()
loss = L(y,z)#z是目标值

词袋(bag of words)模型,文本向量化

输入文本为不等长的符号序列,而神经网络的输入层是固定单元数的,要如何对输入文本进行处理使他变为等长?

使用one-hot编码,以最长文本的长度和字词编码长度的乘积作为输入神经元的数量,但是这样台浪费空间了

词袋模型是一种将文本进行向量化表示的方法,通过统计出词表上的每个单词出现频率,从而将一篇文章向量化

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值