a.flatten():a是个数组,a.flatten()就是把a降到一维,默认是按行的方向降
参考blog
p = np.random.randn(1,26) #生成26个正态分布的数
p = p/p.sum() #归一化
n = np.random.randint(30, 48) #生成长度为30-48个词的句子
x = np.random.choice(words, size = n, replace=True,p=p) #words为字符数组,p为频率
y = y[::-1] #按步长为1从最后一个元素开始取数
y = y[::-3] #按步长为3从最后一个元素开始取数
y = y[3:: ] #按步长为3从最第一个元素开始取数
以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
原文链接: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])]
for i in range(len(numbers)):
print('({0}, {1})'.format(i, numbers[i]))
numbers = [10, 29, 30, 41]
for index, value in enumerate(numbers):
print(index, value)
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
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值)
model.train() :启用 BatchNormalization 和 Dropout,告诉我们的网络,这个阶段是用来训练的,可以更新参数。
model.eval() :不启用 BatchNormalization 和 Dropout,告诉我们的网络,这个阶段是用来测试的,于是模型的参数在该阶段不进行更新。
Dropout: 训练过程中,为防止模型过拟合,增加其泛化性,会随机屏蔽掉一些神经元,相当于输入每次走过不同的“模型”。测试模式时,所有神经元共同作用,类似于boosting。
BN: 训练过程中,模型每次处理一个minibatch数据,BN根据一个minibatch来计算mean和std后做归一化处理,这也是为什么模型的性能和minibatch的大小关系很大(后续也有系列文章来解决BN在小minibatch下表现不佳的问题)。测试时,BN会利用训练时得到的参数来处理测试数据。如果不设置model.eval(),输入单张图像,会报错。
为了使用这个模型,我们把输入数据传给它。这就执行了模型的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__,直接返回其结果。
#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)
print("Model structure: ", model, "\n\n")
for name, param in model.named_parameters():
print(f"Layer: {name} | Size: {param.size()} | Values : {param[:2]} \n")
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()自定义初始化函数来初始化需要的参数
转载
nn.init.xavier_uniform_()
保证输入输出前后向传播的方差一致
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
参考blog
view()的作用相当于numpy中的reshape,重新定义矩阵的形状。
x.view(-1,4)中-1相当于自动调整行数
#[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)来实现
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])
#定义一个网络
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"))