Python/Pytorch相关知识学习

一、Python

1、方法

1、 nn.Flatten()

a.flatten():a是个数组,a.flatten()就是把a降到一维,默认是按行的方向降

2、print()

参考blog

3、随机生成概率和为1的数列

p = np.random.randn(1,26) #生成26个正态分布的数
p = p/p.sum() #归一化

4、np.random.choice() 按频率从数组中取数

n = np.random.randint(30, 48) #生成长度为30-48个词的句子
x = np.random.choice(words, size = n, replace=True,p=p) #words为字符数组,p为频率

5、数组元素逆序

y = y[::-1]  #按步长为1从最后一个元素开始取数
y = y[::-3]  #按步长为3从最后一个元素开始取数
y = y[3:: ]  #按步长为3从最第一个元素开始取数

6、按行读取txt文件做成字典

以user-item用户id点击过的商品id信息为例:
0 4828 774 207 7460 7465 3768 10221 22435 #第一列是user ID,后面全是item ID

def get_data(self,filename):
	lines = open(filename,'r').readlines()
	user_dict = dict()
	
	for l in lines:
	    tmp = l.strip() #删除字符串头尾空白字符
	    inter = [int(i) for i in tmp.split()] #分割元素转成数组 >>[0, 4828, 774, 207, 7460, 7465, 3768, 10221, 22435]
	    user_id, item_ids = inter[0], inter[1:]
	    item_ids = list(set(item_ids))
	    #做成字典
	    user_dict[user_id] = item_ids #>>{0: [22435, 7460, 774, 7465, 10221, 207, 3768, 4828]}

	return user_dict

7、collections.defaultdict()字典防空默认值

原文链接:https://blog.csdn.net/yangsong95/article/details/82319675

Python中通过Key访问字典,当Key不存在时,会引发‘KeyError’异常。为了避免这种情况的发生,可以使用collections类中的defaultdict()方法来为字典提供默认值。

语法格式:
collections.defaultdict([default_factory[, …]])

该函数返回一个类似字典的对象。defaultdict是Python内建字典类(dict)的一个子类,它重写了方法_missing_(key),增加了一个可写的实例变量default_factory,实例变量default_factory被missing()方法使用,如果该变量存在,则用以初始化构造器,如果没有,则为None。其它的功能和dict一样。

第一个参数为default_factory属性提供初始值,默认为None;其余参数包括关键字参数(keyword arguments)的用法,和dict构造器用法一样。

dict = collections.defaultdict(list) #创建一个值为list的空字典
s=[('yellow',1),('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
for k, v in s:
    d[k].append(v)
print(a)
#>>[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

8、返回数组下标

  1. 遍历
for i in range(len(numbers)):
print('({0}, {1})'.format(i, numbers[i]))
  1. 迭代器enumerate
numbers = [10, 29, 30, 41]
for index, value in enumerate(numbers):
print(index, value)
  1. 内置函数list.index()
list1 = [1,22,31,4,6,7,8,23,5,89,90]
f1 = list1.index(22)
f2 = list1.index(5)
print(f1) #1
print(f2) #8

sorted(), 字典排序

users = {'U80234': {'num': 2, 'time': '11/15/2019 12:37:50 PM'},
 'U60458': {'num': 4, 'time': '11/15/2019 7:11:50 AM'}
 }
 
users_reserve = sorted(users.items(),key=lambda x:x[1]['num'],reverse=True)

根据字典的value值排序,key=lambda x: x[0]是一个匿名函数, x返回的是一个元组 x == (‘U80234’: {‘num’: 2, ‘time’: ‘11/15/2019 12:37:50 PM’), 若要取嵌套字典的值,则key=lambda x:x[1]['num'](x[0]是key值,x[1]是value值)

二、Pytorch

1、相关

1、model.train() & model.eval()

model.train() :启用 BatchNormalization 和 Dropout,告诉我们的网络,这个阶段是用来训练的,可以更新参数。

model.eval() :不启用 BatchNormalization 和 Dropout,告诉我们的网络,这个阶段是用来测试的,于是模型的参数在该阶段不进行更新。

Dropout: 训练过程中,为防止模型过拟合,增加其泛化性,会随机屏蔽掉一些神经元,相当于输入每次走过不同的“模型”。测试模式时,所有神经元共同作用,类似于boosting。
BN: 训练过程中,模型每次处理一个minibatch数据,BN根据一个minibatch来计算mean和std后做归一化处理,这也是为什么模型的性能和minibatch的大小关系很大(后续也有系列文章来解决BN在小minibatch下表现不佳的问题)。测试时,BN会利用训练时得到的参数来处理测试数据。如果不设置model.eval(),输入单张图像,会报错。

2、model(x) & forward()

为了使用这个模型,我们把输入数据传给它。这就执行了模型的forward函数,以及一些后台操作。请不要直接调用model.forward()!

在输入数据上调用模型会返回一个10维的tensor,其中包含每个类别的原始预测值。
forward()
在pytorch中大部分方法都继承自torch.nn.Module, 而Module中的__call__(self)函数中会返回forward()函数的结果,因此在pytorch中调用forward()是不用通过"对象.方法"形式实例化对象调用,可以直接通过类名调用。

class X(object):
    def __init__(self, a, b, range):
        self.a = a
        self.b = b
        self.range = range
    def __call__(self, a, b):
        self.a = a
        self.b = b
        print('__call__ with ({}, {})'.format(self.a, self.b))
    def __del__(self, a, b, range):
        del self.a
        del self.b
        del self.range

调用:

>>> xInstance = X(1, 2, 3)
>>> xInstance(1,2)
__call__ with (1, 2)

第一行实例化对象X调用了__init__(self)函数,第二行使用类+参数直接调用__call__() ,而不是xInstance.call(1,2)方式。
forward()相当于嵌入到__call__,直接返回其结果。

3、nn.Sequential()

#nn.Sequential是一个有序模块的容器。数据以定义的顺序通过所有的模块。
#你可以使用 序列容器来组建一个快速的网络,如seq_modules:

seq_modules = nn.Sequential(
    flatten,
    layer1,
    nn.ReLU(),
    nn.Linear(20, 10)
)
input_image = torch.rand(3,28,28)
logits = seq_modules(input_image)

4、查看模型参数

print("Model structure: ", model, "\n\n")

for name, param in model.named_parameters():
    print(f"Layer: {name} | Size: {param.size()} | Values : {param[:2]} \n")

5、torch.nn.Module.apply & 初始化模型参数/权重

torch中的apply函数通过可以不断遍历model的各个模块。实际上其使用的是深度优先算法,apply递归调用自身,直到不存在模块为止。

net = nn.Sequential(nn.Flatten(),
                    nn.Linear(784, 256),
                    nn.ReLU(),
                    nn.Linear(256, 10)
                   )

def init_weights(m):
    if type(m) == nn.Linear:
        nn.init.normal_(m.weight, std = 0.01)
net.apply(init_weights)

相当于apply会遍历net(Sequential)里的每一层,根据init_weights()自定义初始化函数来初始化需要的参数

6、Xavier深度学习网络权重初始化

转载
nn.init.xavier_uniform_()
保证输入输出前后向传播的方差一致

7、矩阵乘法

torch.mul(a, b) 是矩阵a和b对应位相乘,a和b的维度必须相等,比如a的维度是(1, 2),b的维度是(1, 2),返回的仍是(1, 2)的矩阵;
torch.mm(a, b) 是矩阵a和b矩阵相乘,比如a的维度是(1, 2),b的维度是(2, 3),返回的就是(1, 3)的矩阵。
torch.bmm() 强制规定维度和大小相同
torch.matmul() 没有强制规定维度和大小,可以用利用广播机制进行不同维度的相乘操作
————————————————
原文链接:https://blog.csdn.net/irober/article/details/113686080

8、view()

参考blog
view()的作用相当于numpy中的reshape,重新定义矩阵的形状。
x.view(-1,4)中-1相当于自动调整行数

9、permute()维度变换顺序

#[b,50,32] -> [b,4,50,8]
Q = Q.reshape(b,50,4,8).permute(0,2,1,3)

0 1 2 3对应的是原来tensor的维度位置,0-b, 1-20, 2-4, 3-8,要把[b,50,4,8]变为[b,4,50,8]可通过.permute(0,2,1,3)来实现

10、unsqueeze(0) 升维

unsqueeze()函数起升维的作用,参数表示在哪个地方加一个维度。0表示在张量最外层加一个中括号变成第一维。

import torch
input=torch.arange(0,6)
print(input)
print(input.shape)
结果:
tensor([0, 1, 2, 3, 4, 5])
torch.Size([6])
print(input.unsqueeze(0))
print(input.unsqueeze(0).shape)
结果:
tensor([[0, 1, 2, 3, 4, 5]])
torch.Size([1, 6])
print(input.unsqueeze(1))
print(input.unsqueeze(1).shape)
结果:
tensor([[0],
        [1],
        [2],
        [3],
        [4],
        [5]])
torch.Size([6, 1])

2、pytorch 训练流程

流程

#定义一个网络
class NeuralNetwork(nn.Module):
    def __init__(self):
        super(NeuralNetwork,self).__init__()
        self.flatten = nn.Flatten()
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(28*28, 512),
            nn.ReLU(),
            nn.Linear(512,512),
            nn.ReLU(),
            nn.Linear(512,10)
        )
    
    def forward(self, x):
        x = self.flatten(x)
        logits = self.linear_relu_stack(x)
        return logits
#实例化model
model = NeuralNetwork().to(device)
#定义损失函数和优化器
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr = 1e-3)
#定义训练
def train(dataloader,model,loss_fn,optimizer):
    size = len(dataloader.dataset)
    model.train()
    for batch, (X, y) in enumerate(dataloader):
        X,y = X.to(device),y.to(device) # X是输入数据,y是输出标签
        pred = model(X)    	#model前向传播得到输出的10个预测值
        loss = loss_fn(pred, y) 	#交叉熵损失计算预测值和真实值的损失
        optimizer.zero_grad()		# 梯度置零,因为反向传播过程中梯度会累加上一次循环的梯度
        loss.backward()				#loss反向传播
        optimizer.step()			#反向传播后更新w、b等参数
        
        if batch % 100 == 0:
            loss, current = loss.item(), batch * len(X)
            print(f"loss:{loss:>7f} [{current:>5d}/{size:>5d}]")
  • 调用optimizer.zero_grad()来重置模型参数的梯度。梯度默认为累加;为了防止重复计算,我们在每次迭代中明确地将其归零。

  • 通过调用loss.backwards()对预测损失进行反向传播。PyTorch将损失的梯度与每个参数联系在一起。

  • 一旦我们有了梯度,我们就可以调用optimizer.step()来根据向后传递中收集的梯度调整参数。

#定义测试
def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    model.eval()
    test_loss, correct = 0,0
    with torch.no_grad():    			#不会进行梯度计算
        for X, y in dataloader:
            X,y = X.to(device),y.to(device)
            pred = model(X)
            test_loss += loss_fn(pred,y).item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()
        test_loss /= num_batches
        correct /=size
        print(f"Test Error: \n Accuracy:{(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
            
#训练测试
epochs = 5
for t in range(epochs):
    print(f"Epoch{t+1}\n------")
    train(train_dataloader,model, loss_fn, optimizer)
    test(test_dataloader, model, loss_fn)
print("Done")
#保存模型
torch.save(model.state_dict(),"./model_ht.pth")
print("Saved Pytorch Model State to model_ht.pth")
#加载模型
model = NeuralNetwork()
model.load_state_dict(torch.load("model_ht.pth"))

你可能感兴趣的:(AI,pytorch,python,深度学习)