因为在学习人工智能相关知识,于是将学习过程与程序放在这里,希望对大家有帮助,共同学习,共同进步(不喜勿喷)
回归问题是基于已有数据对新的数据进行预测,如预测股票走势。这里我们主要讲简单的线性回归。
下面举一个简单的例子:
假设我们想要求出橘子的产量在天气,温度,湿度等情况下的关系,那么我们就可以用线性回归来求解。那么我们假设橘子的产量为y,天气为x1,温度为x2,湿度为x3。那么产量y与x1,x2,x3的关系为:
那么写成向量形式就是:
那么接下来要求的就是最适合的w和b,那么怎么判断w和b最合适呢,那就要用到损失函数(Loss).
在回归问题中常用的损失函数是均方差损失(MSE),回归中的输出是一个实数值,这里采样的平方损失函数类似于线性回归中的最小二乘法。对于每个输入实例都有一个输出值,在将所有输入实例预测值和真实值间的误差求平方,取平均。
那么在计算机当中如何实现呢,我们随机设定w和b的值,此时得到的y为模型的预测值记作
那么损失就为
接下来我们的问题就转化为了求最小Loss的问题。而为了得到最新的Loss,采用的方法为梯度下降法。
梯度下降法的基本思想可以类比为一个下山的过程。
假设这样一个场景:一个人被困在山上,需要从山上下来(找到山的最低点,也就是山谷)。但此时山上的浓雾很大,导致可视度很低;因此,下山的路径就无法确定,必须利用自己周围的信息一步一步地找到下山的路。这个时候,便可利用梯度下降算法来帮助自己下山。怎么做呢,首先以他当前的所处的位置为基准,寻找这个位置最陡峭的地方,然后朝着下降方向走一步,然后又继续以当前位置为基准,再找最陡峭的地方,再走直到最后到达最低处;同理上山也是如此,只是这时候就变成梯度上升算法了
#导入要用到的库
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
import time
x = np.ones((10000,1000))
inputs = x+np.random.rand(10000,1000)
targets = np.ones((10000,1))
#将numpy转化为tensor 并设为float32类型
inputs = torch.from_numpy(inputs)
targets = torch.from_numpy(targets)
inputs = torch.as_tensor(inputs,dtype=torch.float32)
targets = torch.as_tensor(targets,dtype=torch.float32)
#创建权重和偏置的初始化矩阵
model = nn.Linear(1000,1)
#创建一个TensorDataset,可以读取 inputs 和 targets 的行作为元组
from torch.utils.data import TensorDataset
#将inputs,targets放入train_ds中
train_ds=TensorDataset(inputs,targets)
from torch.utils.data import DataLoader#创建一个 DataLoader,它可以在训练时将数据分成预定义大小的批次。它还能提供其它效用程序,如数据的混洗和随机采样
batch_size=10#设定一次运行的数据量
#在每次迭代中,数据加载器都会返回一批给定批大小的数据。如果 shuffle 设为 True,则在创建批之前会对训练数据进行混洗。混洗能帮助优化算法的输入随机化,这能实现损失的更快下降。
train_dl=DataLoader(train_ds,batch_size,shuffle=True)
preds = model(inputs)#得到模拟值但是和真实值之相差较大
loss_fn = nn.MSELoss()#定义损失函数 预测值和真实值差值平方的平均数
loss = loss_fn(preds,targets)
opt= torch.optim.SGD(model.parameters(),lr=0.0001)#选择优化器 SGD为随机梯度下降函数
def fit(num_epochs,model,loss_fn,opt):
px,py=[],[]
for epoch in range(num_epochs):
for xb,yb in train_dl:
pred=model(xb)
loss = loss_fn(pred,yb)#计算损失
loss.backward()#梯度下降函数
opt.step()#用opt.step()实现model中的w和b的改变
opt.zero_grad()
px.append(epoch)
py.append(loss.item())
if(epoch+1)%10==0:
print("Epoch[{}/{}],Loss:{:.4f}".format(epoch+1,num_epochs,loss.item()))
if epoch % 10 ==0:
plt.cla()
plt.plot(px,py,'r-',lw=1)
start = time.perf_counter()
fit(100,model,loss_fn,opt)
elapsed = (time.perf_counter() - start)
print("Time used:",elapsed)
运行结果如下图所示:
此时会发现用cpu运行的时间很长,那我们将其设置为给gpu模式下运行,将代码改为
#导入要用到的库
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
import time
use_cuda = torch.cuda.is_available()#检查gpu是否可用
x = np.ones((10000,1000))
inputs = x+np.random.rand(10000,1000)
targets = np.ones((10000,1))
#将numpy转化为tensor 并设为float32类型
inputs = torch.from_numpy(inputs)
targets = torch.from_numpy(targets)
inputs = torch.as_tensor(inputs,dtype=torch.float32)
targets = torch.as_tensor(targets,dtype=torch.float32)
#创建权重和偏置的初始化矩阵
model = nn.Linear(1000,1)
#创建一个TensorDataset,可以读取 inputs 和 targets 的行作为元组
if use_cuda:#如果gpu可用,将数据和模型都放到gpu中
inputs=inputs.cuda()
targets = targets.cuda()
model=model.cuda()
from torch.utils.data import TensorDataset
#将inputs,targets放入train_ds中
train_ds=TensorDataset(inputs,targets)
from torch.utils.data import DataLoader#创建一个 DataLoader,它可以在训练时将数据分成预定义大小的批次。它还能提供其它效用程序,如数据的混洗和随机采样
batch_size=10#设定一次运行的数据量
#在每次迭代中,数据加载器都会返回一批给定批大小的数据。如果 shuffle 设为 True,则在创建批之前会对训练数据进行混洗。混洗能帮助优化算法的输入随机化,这能实现损失的更快下降。
train_dl=DataLoader(train_ds,batch_size,shuffle=True)
preds = model(inputs)#得到模拟值但是和真实值之相差较大
loss_fn = nn.MSELoss()#定义损失函数 预测值和真实值差值平方的平均数
loss = loss_fn(preds,targets)
opt= torch.optim.SGD(model.parameters(),lr=0.0001)#选择优化器 SGD为随机梯度下降函数
def fit(num_epochs,model,loss_fn,opt):
px,py=[],[]
for epoch in range(num_epochs):
for xb,yb in train_dl:
pred=model(xb)
loss = loss_fn(pred,yb)
loss.backward()
opt.step()#用opt.step()实现model中的w和b的改变
opt.zero_grad()
px.append(epoch)
py.append(loss.item())
if(epoch+1)%10==0:
print("Epoch[{}/{}],Loss:{:.4f}".format(epoch+1,num_epochs,loss.item()))
if epoch % 10 ==0:
plt.cla()
plt.plot(px,py,'r-',lw=1)
start = time.perf_counter()
fit(100,model,loss_fn,opt)#运行100次计算时间
elapsed = (time.perf_counter() - start)
print("Time used:",elapsed)
此时发现运算时间大大加长,查资料得到gpu善于并行运算,而将数据分为10个一组显然是不正确的。于是删掉代码中的
from torch.utils.data import TensorDataset
#将inputs,targets放入train_ds中
train_ds=TensorDataset(inputs,targets)
from torch.utils.data import DataLoader#创建一个 DataLoader,它可以在训练时将数据分成预定义大小的批次。它还能提供其它效用程序,如数据的混洗和随机采样
batch_size=10#设定一次运行的数据量
#在每次迭代中,数据加载器都会返回一批给定批大小的数据。如果 shuffle 设为 True,则在创建批之前会对训练数据进行混洗。混洗能帮助优化算法的输入随机化,这能实现损失的更快下降。
train_dl=DataLoader(train_ds,batch_size,shuffle=True)
将代码归改为
#导入要用到的库
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
import time
use_cuda = torch.cuda.is_available()#检查gpu是否可用
x = np.ones((10000,1000))
inputs = x+np.random.rand(10000,1000)
targets = np.ones((10000,1))
#将numpy转化为tensor 并设为float32类型
inputs = torch.from_numpy(inputs)
targets = torch.from_numpy(targets)
inputs = torch.as_tensor(inputs,dtype=torch.float32)
targets = torch.as_tensor(targets,dtype=torch.float32)
#创建权重和偏置的初始化矩阵
model = nn.Linear(1000,1)
#创建一个TensorDataset,可以读取 inputs 和 targets 的行作为元组
if use_cuda:#如果gpu可用,将数据和模型都放到gpu中
inputs=inputs.cuda()
targets = targets.cuda()
model=model.cuda()
preds = model(inputs)#得到模拟值但是和真实值之相差较大
loss_fn = nn.MSELoss()#定义损失函数 预测值和真实值差值平方的平均数
loss = loss_fn(preds,targets)
opt= torch.optim.SGD(model.parameters(),lr=0.0001)#选择优化器 SGD为随机梯度下降函数
def fit(num_epochs,model,loss_fn,opt):
px,py=[],[]
for epoch in range(num_epochs):
pred=model(inputs)
loss = loss_fn(pred,targets)
loss.backward()
opt.step()#用opt.step()实现model中的w和b的改变
opt.zero_grad()
px.append(epoch)
py.append(loss.item())
if(epoch+1)%10==0:
print("Epoch[{}/{}],Loss:{:.4f}".format(epoch+1,num_epochs,loss.item()))
if epoch % 10 ==0:
plt.cla()
plt.plot(px,py,'r-',lw=1)
start = time.perf_counter()
fit(100,model,loss_fn,opt)#运行100次计算时间
elapsed = (time.perf_counter() - start)
print("Time used:",elapsed)
运算速度大大提升,由此可知gpu在运算时比cpu运算的速度快的多。
import numpy as np
import tensorflow as tf
px,py=[],[]
x = np.ones((10000,1000))
inputs = x+np.random.rand(10000,1000)
targets = np.ones((10000,1))
X = tf.constant(inputs,dtype=tf.float32)#创建一个tensor常量
y = tf.constant(targets,dtype=tf.float32)
a = tf.Variable(initial_value=0.)
b = tf.Variable(initial_value=0.)
variables = [a, b]
num_epoch = 100
optimizer = tf.keras.optimizers.SGD(learning_rate=0.0001)
# 定义随机梯度下降法中的优化器和学习率
start = time.perf_counter()
for e in range(num_epoch):
# 使用tf.GradientTape()记录损失函数的梯度信息
with tf.GradientTape() as tape:
y_pred = a * X + b#计算损失函数
loss = tf.reduce_mean(tf.square(y_pred - y))#对每一个数平方并累加
px.append(e)
py.append(loss)
# TensorFlow自动计算损失函数关于自变量(模型参数)的梯度
grads = tape.gradient(loss, variables)
# TensorFlow自动根据梯度更新参数
optimizer.apply_gradients(grads_and_vars=zip(grads, variables))
if num_epoch % 10 ==0:
plt.cla()
plt.plot(px,py,'r-',lw=1)
print(loss)
elapsed = (time.perf_counter() - start)
print("Time used:",elapsed)
可以看出tensorflow在相同学习率与计算次数的情况下运行的速度不如pytorch
pytorch在1000次运行下的计算时间
tensorflow在1000次运行下的计算时间
比较之下,在线性回归的计算中pytorch更胜一筹
相同的学习率以及计算次数下,gpu比cpu运算速度更快,同时pytorch比tensorflow更快,顺带一提,在cpu的运行速度比较上,tensorflow比pytorch更快。
本人为新人,还在学习阶段如果有写的不正确的地方欢迎大佬指正,不喜勿喷。