pytorch和tensorflow的爱恨情仇之基本数据类型

pytorch和tensorflow的爱恨情仇之张量

pytorch版本:1.6.0

tensorflow版本:1.15.0

之前我们就已经了解了pytorch和tensorflow中的变量,本节我们深入了解可训练的参数-变量

接下来我们将使用sklearn自带的iris数据集来慢慢品味。

1、pytorch

(1)第一种方式,不使用nn.Module或nn.Sequntial()来建立模型的情况下自定义参数;

加载数据集并转换为tensot:

  1. import torch
  2. import torch.nn.functional as F
  3. import numpy as np
  4. from sklearn.datasets import load_iris
  5. iris = load_iris()
  6. data=iris.data
  7. target = iris.target
  1. data = torch.from_numpy(data).float() #(150,4)
  2. target = torch.from_numpy(target).long() #(150,3)
  3. batch_size=data.shape[0] #设置batchsize的大小就是所有数据
  4. dataset = torch.utils.data.TensorDataset(data, target) # 设置数据集
  5. train_iter = torch.utils.data.DataLoader(dataset, batch_size, shuffle=True) # 设置获取数据方式

自己定义好要训练的参数:

  1. classes = 3
  2. input = 4
  3. hidden = 10
  4.  
  5. w_0 = torch.tensor(np.random.normal(0, 0.01, (input, hidden)), dtype=torch.float)
  6. b_0 = torch.zeros(hidden, dtype=torch.float)
  7. w_1 = torch.tensor(np.random.normal(0, 0.01, (hidden, classes)), dtype=torch.float)
  8. b_1 = torch.zeros(classes, dtype=torch.float)

我们可以在定义参数的时候指定requires_grad=True使其为可训练的参数,也可以使用如下方式:

  1. params = [w_0, b_0, w_1, b_1]
  2. for param in params:
  3. param.requires_grad_(requires_grad=True)

定义学习率、优化器、损失函数、网络

  1. lr = 5
  2. optimizer = None
  3. criterion = torch.nn.CrossEntropyLoss()
  4. epoch = 1000
  5.  
  6. def sgd(params, lr, batch_size):
  7. for param in params:
  8. param.data -= lr * param.grad / batch_size # 注意这里更改param时用的param.data
  9.  
  10. def net(x):
  11. h = torch.matmul(x,w_0)+b_0
  12. h = F.relu(h)
  13. output = torch.matmul(h,w_1)+b_1
  14. #output = F.softmax(output,dim=1)
  15. return output

为了更加清楚参数训练的过程,这里我们不使用pytorch自带的,而是我们自己定义的随机梯度下降。

定义训练主函数:

  1. def train(net,params,lr,train_iter):
  2. for i in range(1,epoch+1):
  3. for x,y in train_iter:
  4. output = net(x)
  5. loss = criterion(output,y)
  6. # 梯度清零
  7. if optimizer is not None:
  8. optimizer.zero_grad()
  9. elif params is not None and params[0].grad is not None:
  10. for param in params:
  11. param.grad.data.zero_()
  12. loss.backward()
  13. if optimizer is None:
  14. sgd(params, lr, batch_size)
  15. else:
  16. optimizer.step() # “softmax回归的简洁实现”一节将用到
  17. acc = (output.argmax(dim=1) == y).sum().item() / data.shape[0]
  18. print("epoch:{:03d} loss:{:.4f} acc:{:.4f}".format(i,loss.item(),acc))
  19. train(net=net,params=params,lr=lr,train_iter=train_iter)

从这里我们也可以看到optimizer.zero_grad()和optimizer.step()的作用了,以上便是我们自定义训练参数的完整过程了,看下结果:

  1. epoch:994 loss:0.0928 acc:0.9800
  2. epoch:995 loss:0.0927 acc:0.9800
  3. epoch:996 loss:0.0926 acc:0.9800
  4. epoch:997 loss:0.0926 acc:0.9800
  5. epoch:998 loss:0.0925 acc:0.9800
  6. epoch:999 loss:0.0925 acc:0.9800
  7. epoch:1000 loss:0.0924 acc:0.9800

(2)使用nn.Sequential()来构建模型,进行参数初始化:

导入相应的包并加载数据集:

  1. import torch
  2. import torch.nn as nn
  3. import torch.nn.init as init
  4. import torch.nn.functional as F
  5. import numpy as np
  6. from sklearn.datasets import load_iris
  7. iris = load_iris()
  8. data=iris.data
  9. target = iris.target

转换为pytorch数据格式:

  1. data = torch.from_numpy(data).float()
  2. target = torch.from_numpy(target).long()
  3. batch_size=data.shape[0]
  4. dataset = torch.utils.data.TensorDataset(data, target) # 设置数据集
  5. train_iter = torch.utils.data.DataLoader(dataset, batch_size, shuffle=True) # 设置获取数据方式

定义相关超参数:

  1. classes = 3
  2. input = 4
  3. hidden = 10
  4. lr = 4
  5. optimizer = None

定义网络:

  1. net = nn.Sequential(
  2. nn.Linear(input,hidden),
  3. nn.ReLU(),
  4. nn.Linear(hidden,classes),
  5. )

参数初始化:

  1. for name,param in net.named_parameters(): #使用model.named_parameters()可以获得相应层的名字的参数以及具体值
  2. if "weight" in name:
  3. init.normal_(param, mean=0, std=0.01)
  4. if "bias" in name:
  5. init.zeros_(param)

自定义随机梯度下降优化器:

  1. def sgd(params, lr, batch_size):
  2. for param in params:
  3. param.data -= lr * param.grad / batch_size # 注意这里更改param时用的param.data

训练主循环:

  1. epoch = 1000
  2. criterion = torch.nn.CrossEntropyLoss()
  3. def train(net,lr,train_iter):
  4. for i in range(1,epoch+1):
  5. for x,y in train_iter:
  6. output = net(x)
  7. loss = criterion(output,y)
  8. # 梯度清零
  9. if optimizer is not None:
  10. optimizer.zero_grad()
  11. elif net.parameters() is not None:
  12. for param in net.parameters():
  13. if param.grad is not None:
  14. param.grad.data.zero_()
  15. loss.backward()
  16. if optimizer is None:
  17. sgd(net.parameters(), lr, batch_size)
  18. else:
  19. optimizer.step() # “softmax回归的简洁实现”一节将用到
  20. acc = (output.argmax(dim=1) == y).sum().item() / data.shape[0]
  21. print("epoch:{:03d} loss:{:.4f} acc:{:.4f}".format(i,loss.item(),acc))
  22. return
  23. train(net=net,lr=lr,train_iter=train_iter)

结果:

(3) 使用pytorch自带的优化器

我们只需要将opyimizer设置为以下即可:

  1. optimizer = torch.optim.SGD(net.parameters(), lr=0.05)

需要注意的是学习率这里需要设置的比较小一点,和上面设置的有所不同,结果如下:

(4) 使用nn.Module来构建网络,自定义参数并进行初始化

我们只需要修改以下地方即可:

  1. class Net(nn.Module):
  2. def __init__(self,input,hidden,classes):
  3. super(Net, self).__init__()
  4. self.input = input
  5. self.hidden = hidden
  6. self.classes = classes
  7.  
  8. self.w0 = nn.Parameter(torch.Tensor(self.input,self.hidden))
  9. self.b0 = nn.Parameter(torch.Tensor(self.hidden))
  10. self.w1 = nn.Parameter(torch.Tensor(self.hidden,self.classes))
  11. self.b1 = nn.Parameter(torch.Tensor(self.classes))
  12. self.reset_parameters()
  13.  
  14. def reset_parameters(self):
  15. nn.init.normal_(self.w0)
  16. nn.init.constant_(self.b0,0)
  17. nn.init.normal_(self.w1)
  18. nn.init.constant_(self.b1,0)
  19.  
  20. def forward(self,x):
  21. out = torch.matmul(x,self.w0)+self.b0
  22. out = F.relu(out)
  23. out = torch.matmul(out,self.w1)+self.b1
  24. return out
  25. net = Net(input,hidden,classes)
  26. optimizer = torch.optim.SGD(net.parameters(), lr=0.05)

结果:

(4) 使用nn.Module()构建网路,并使用各层中的参数并进行初始化

  1. class Net(nn.Module):
  2. def __init__(self,input,hidden,classes):
  3. super(Net, self).__init__()
  4. self.input = input
  5. self.hidden = hidden
  6. self.classes = classes
  7. self.fc1 = nn.Linear(self.input,self.hidden)
  8. self.fc2 = nn.Linear(self.hidden,self.classes)
  9.  
  10. for m in self.modules():
  11. if isinstance(m, nn.Linear):
  12. nn.init.normal_(m.weight,0,0.01)
  13. nn.init.constant_(m.bias, 0)
  14.  
  15. def forward(self,x):
  16. out = self.fc1(x)
  17. out = F.relu(out)
  18. out = self.fc2(out)
  19. return out
  20. net = Net(input,hidden,classes)
  21. optimizer = torch.optim.SGD(net.parameters(), lr=0.05)

结果:

PyTorch 中参数的默认初始化在各个层的 reset_parameters() 方法

我们看下官方的Linear层的实现:

  1. 官方Linear层:
  2. class Linear(Module):
  3. def __init__(self, in_features, out_features, bias=True):
  4. super(Linear, self).__init__()
  5. self.in_features = in_features
  6. self.out_features = out_features
  7. self.weight = Parameter(torch.Tensor(out_features, in_features))
  8. if bias:
  9. self.bias = Parameter(torch.Tensor(out_features))
  10. else:
  11. self.register_parameter('bias', None)
  12. self.reset_parameters()
  13.  
  14. def reset_parameters(self):
  15. stdv = 1. / math.sqrt(self.weight.size(1))
  16. self.weight.data.uniform_(-stdv, stdv)
  17. if self.bias is not None:
  18. self.bias.data.uniform_(-stdv, stdv)
  19.  
  20. def forward(self, input):
  21. return F.linear(input, self.weight, self.bias)
  22.  
  23. def extra_repr(self):
  24. return 'in_features={}, out_features={}, bias={}'.format(
  25. self.in_features, self.out_features, self.bias is not None
  26. )

(5) 最后我们来看下从网络中获取参数名字和参数值的一些例子

我们以这个网络为例:

  1. class Net(nn.Module):
  2. def __init__(self,input,hidden,classes):
  3. super(Net, self).__init__()
  4. self.input = input
  5. self.hidden = hidden
  6. self.classes = classes
  7. self.fc1 = nn.Linear(self.input,self.hidden)
  8. self.fc2 = nn.Linear(self.hidden,self.classes)
  9.  
  10. for m in self.modules():
  11. if isinstance(m, nn.Linear):
  12. nn.init.normal_(m.weight,0,0.01)
  13. nn.init.constant_(m.bias, 0)
  14.  
  15. def forward(self,x):
  16. out = self.fc1(x)
  17. out = F.relu(out)
  18. out = self.fc2(out)
  19. return out
  20. net = Net(input,hidden,classes)

首先是model.state_dict():是一个参数字典,键是参数的名称,值是参数的值:

  1. for name,value in net.state_dict().items():
  2. print(name,value)

接着是:model.parameters():返回的是一个generator,我们之前也经常使用,通过param.data,param.data.grad来获取参数的值以及梯度

  1. for param in net.parameters():
  2. print(param.data,param.grad)

接着是model.named_parameters():返回的是一个具名参数,也就是包含了参数的名称

  1. for name,param in net.named_parameters():
  2. print(name,param)

最后讲下的是self.modules():一般是在网络初始化中使用,返回的是网络中的具体层,我们可以通过其对不同层进行参数初始化,比如nn.Conv2d、nn.Linear等;

参考:

https://www.cnblogs.com/KaifengGuan/p/12332072.html

https://www.geekschool.org/2020/08/02/13455.html

https://blog.csdn.net/weixin_44058333/article/details/92691656

(2)tensorflow

导入相应的包并加载数据:

  1. import tensorflow as tf
  2. import numpy as np
  3. from sklearn.datasets import load_iris
  4. from sklearn.preprocessing import OneHotEncoder
  5. iris = load_iris()
  6. data=iris.data
  7. target = iris.target

将标签转换为onehot编码:

  1. oneHotEncoder = OneHotEncoder(sparse=False)
  2. onehot_target = oneHotEncoder.fit_transform(target.reshape(-1,1))
  3. print(onehot_target)

定义超参数以及可训练的参数:

  1. input=4
  2. hidden=10
  3. classes=3
  4. w0=tf.Variable(tf.random.normal([input,hidden],stddev=0.01,seed=1))
  5. b0=tf.Variable(tf.zeros([hidden]))
  6. w1=tf.Variable(tf.random.normal([hidden,classes],stddev=0.01,seed=1))
  7. b1=tf.Variable(tf.zeros([classes]))

定义计算图中的占位符:

  1. x = tf.placeholder(tf.float32,shape=(None,input),name="x-input") #输入数据
  2. y_ = tf.placeholder(tf.float32,shape=(None,classes),name="y-input") #真实标签

定义网络、损失函数和优化器:

  1. def net(x):
  2. hid = tf.add(tf.matmul(x,w0),b0)
  3. hid = tf.nn.relu(hid)
  4. out = tf.add(tf.matmul(hid,w1),b1)
  5. out = tf.nn.softmax(out)
  6. return out
  7. y = net(x)
  8. cross_entropy = -tf.reduce_mean(y_*tf.log(tf.clip_by_value(y,1e-10,1.0)) \
  9. + (1-y_)*tf.log(tf.clip_by_value(1-y,1e-10,1.0)))
  10.  
  11. optimizer=tf.compat.v1.train.GradientDescentOptimizer(learning_rate=0.05).minimize(cross_entropy)

训练循环:

  1. epoch = 1000
  2. with tf.compat.v1.Session() as sess: #建立会话
  3. init_op = tf.global_variables_initializer() #初始化参数
  4. sess.run(init_op)
  5. for epoch in range(1,epoch+1):
  6. sess.run(optimizer,feed_dict={x:data,y_:onehot_target}) #传入数据给优化器
  7. y_pred = sess.run(y,feed_dict={x:data}) #计算输出
  8. total_cross_entropy = sess.run(cross_entropy,feed_dict={y:y_pred,y_:onehot_target}) #计算交叉熵
  9. pred = tf.argmax(y_pred,axis = 1) # 取出行中最大值的索引,也就是取出其中概率最大的索引
  10.  
  11. correct = tf.cast(tf.equal(pred,target),dtype=tf.int32) # 判断与测试集的标签是否相等并且转换bool为int型
  12. correct = tf.reduce_sum(correct) # 沿着指定维度的和,不指定axis则默认为所有元素的和
  13. acc = correct.eval() / data.shape[0]
  14. print("epoch:{} loss:{:.4f} acc:{:.4f}".format(epoch, total_cross_entropy,acc))

结果:

但感觉训练1000个epoch比pytorch慢好多。。

pytorch和tensorflow的爱恨情仇之定义可训练的参数的更多相关文章

  1. pytorch和tensorflow的爱恨情仇之参数初始化

    pytorch和tensorflow的爱恨情仇之基本数据类型 pytorch和tensorflow的爱恨情仇之张量 pytorch和tensorflow的爱恨情仇之定义可训练的参数 pytorch版本 ...

  2. pytorch和tensorflow的爱恨情仇之基本数据类型

    自己一直以来都是使用的pytorch,最近打算好好的看下tensorflow,新开一个系列:pytorch和tensorflow的爱恨情仇(相爱相杀...) 无论学习什么框架或者是什么编程语言,最基础 ...

  3. pytorch和tensorflow的爱恨情仇之张量

    pytorch和tensorflow的爱恨情仇之基本数据类型:https://www.cnblogs.com/xiximayou/p/13759451.html pytorch版本:1.6.0 ten ...

  4. pytorch和tensorflow的爱恨情仇之一元线性回归例子(keras插足啦)

    直接看代码: 一.tensorflow #tensorflow import tensorflow as tf import random import numpy as np x_data = np ...

  5. Menu与ActionBar的爱恨情仇

    最近在开发一款音乐播放器,在开发过程中遇到了一点小麻烦,通过android API搞清楚了Menu与ActionBar的爱恨情仇,写了个小Demo祭奠一下那些年我们陷进去的坑,有不对的地方请大神们批评 ...

  6. web移动端fixed布局和input等表单的爱恨情仇 - 终极BUG,完美解决

    [问题]移动端开发,ios下当fixed属性和输入框input(这里不限于input,只要可以调用移动端输入法的都包括,如:textarea.HTML5中contenteditable等),同时存在的 ...

  7. 注解:大话AOP与Android的爱恨情仇

    转载:大话AOP与Android的爱恨情仇 1. AOP与OOP的区别 平时我接触多的就是OOP(Object Oriented Programming面向对象).AOP(Aspect Oriente ...

  8. 除了love和hate,还能怎么表达那些年的“爱恨情仇”?

    实用英语 帮你全面提高英语水平 关注 童鞋们每次刷美剧的时候,相信都会被CP感满满的男女主角虐得体无完肤吧. 可是,一到我们自己表达爱意或者恨意的时候,却苦于词穷,只会用love, like, hat ...

  9. 对json的爱恨情仇

    本文回想了对json的爱恨情仇. C++有风险,使用需慎重. 本文相关代码在:http://download.csdn.net/detail/baihacker/7862785 当中的測试数据不在里面 ...

随机推荐

  1. SwiftUI - Grid View 的实现方法,逐步剖析助你实现

    简介 在当前正式 SwiftUI 版本而言,很多控件都是缺少的.比如在 UIKit 框架里有 UICollectionView 组件,可以很方便地做 Gird 格子类型的视图.但是在 SwiftUI ...

  2. 由mv命令引发的对inode的思考

    一场机器迁移引起的思考 最近团队一台机器老化了,准备做全量迁移,一不小心,就把100多个G的/data目录放到了新机器的/data/data目录下,上愁了,怎么削减一层data目录呢?难倒像Windo ...

  3. Android开发之清除缓存功能实现方法,可以集成在自己的app中,增加一个新功能。

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 Android开发之清除缓存功能实现方法,可以集成在自己的app中,增加一个新功能. 下面是一个效果图 ...

  4. ajax发送请求的时候url为空或者undefined会发生什么

    $.ajax()里的url为空,ajax请求发送到当前自己的页面. 例如index.html里$.ajax()的url为空就发送到index.html

  5. 把Employees显示在页面上

    项目代码下载:https://files.cnblogs.com/files/xiandedanteng/gatling20200429-1.zip 需求:从后台DB取出雇员数据,显示在前台页面上: ...

  6. 写Junit测试时用Autowired注入的类实例始终为空怎么解?

    踩坑半天多,终于在网上寻觅到了解决方案,特此分享一下. 重要前提:src/main/java下的根包名必须和src/test/main的根包名完全一致,否则就会发生死活不能注入的情况,要继续进行下面的 ...

  7. HTML标签语言一览表

    <html> ● 文件声明 让浏览器知道这是 html 文件 <head> ● 开头 提供文件整体资讯 <title> ● 标题 定义文件标题,将显示于浏览顶端 & ...

  8. Solr专题(二)详解Solr查询参数

    一.前言 上节我们讲到了怎样去搭建solr服务,作为全文检索引擎,怎样去使用也是比较关键的.Solr有一套自己的查询方式,所以我们需要另外花时间去学习它的这套模式. 启动solr solr start ...

  9. Django+bootstrap启动登录模板页面(Django三)

    上次用Django启动了我的第一个页面 具体步骤参考:初步启动DjangoDjango启动第一个页面但是页面非常简陋,所以我从网上找了个模板,下载网址:免费下载模板,解压后内部文件如下: 效果图:下面 ...

  10. mysql版本和模式查询

    查找数据库的: select version() select @@sql_mode 上面是查版本号,下面是查sql-mode,改sql-model要在mysql目录下配置文件 my.ini, 改修改 ...