基础知识
常用函数数据处理建立NNTraining Day2
dim的一些理解保证随机数种子一样实例变量和类变量matplotlibHW1
对数据进行预处理,然后加载数据:建立神经网络:训练过程:整体流程: Day3
强化学习 HW教程 HW2
搭建网络顺序类与继承 VirtualTaobao代码
基础知识- import torch.nn as nntorch.nn.Linear(in_features,out_features,bias)用于建立全连接层。in_features指的是输入的二维张量的大小,out_features指的是输出的二维张量的大小,也代表了该全连接层的神经元个数。
layer = torch.nn.Linear(30,5) input = torch.randn(12,30) layer(input) # 输出12x5
- torch.nn.Parameter()类型转换函数,将一个不可训练的类型Tensor转换成可以训练的类型parameter并将这个parameter绑定到这个module里面torch.mm(a, b)矩阵a和b矩阵相乘; torch.mul(a, b)是矩阵a和b对应位相乘;fillna()用于填充dataframe的缺失值 参数设置LabelEncoder()(对不连续的数字或者文本进行数字化处理)将离散型的数据转换成 0~n−1 之间的数。
le = LabelEncoder() le.fit(["paris", "paris", "tokyo", "amsterdam"]) print(le.classes_) # ['amsterdam' 'paris' 'tokyo'] print(le.transform(["tokyo", "tokyo", "paris"])) # [2 2 1]
注意了注意了,这个函数会先去掉重复值,再排序(字母顺序/数字大小)并一一对应上数字,,最后返回target对应的数字
le = LabelEncoder() print(le.fit_transform(["boy", "a", "cat"])) # [1 0 2]
- sklearn.preprocessing.MinMaxScaler(feature_range=(0, 1), copy=True)数据归一化
x
−
m
i
n
m
a
x
−
m
i
n
frac{x-min}{max-min}
max−minx−min。需要传入二维的数据,如果非要传入一维的数据,需要reshapereshape(-1,1)unique()是以数组形式(numpy.ndarray)返回列的所有唯一值(特征的所有唯一值)nunique()即返回的是dataframe中唯一值的个数sklearn.metrics.log_loss(y_true, y_pred, *, eps=1e-15, normalize=True, sample_weight=None, labels=None) 需要传入onehot值isinstance() 函数来判断一个对象是否是一个已知的类型hasattr() 函数用于判断对象是否包含对应的属性torch.nn.Embedding(num_embeddings, embedding_dim) 建一个词嵌入模型,num_embeddings代表一共有多少个词, embedding_dim代表你想要为每个词创建一个多少维的向量来表示它。(就是随机初始化一个矩阵,可以通过索引寻找embed = embedding(torch.LongTensor(word))
embedding=torch.nn.Embedding(3,5) # 3*5的矩阵 res = embedding(torch.LongTensor([2])) # 返回索引为2的向量
- nn.ModuleList(),是一个储存不同module,并自动将每个 module 的 parameters 添加到网络之中的容器。你可以把任意 nn.Module 的子类 (比如 nn.Conv2d, nn.Linear 之类的) 加到这个 list 里面,方法和 Python 自带的 list 一样,无非是 extend,append 等操作。nn.Sequential:里面的模块按照顺序进行排列的,所以必须确保前一个模块的输出大小和下一个模块的输入大小是一致的。
来源:李宏毅机器学习
- torch.squeeze() 对数据的维度进行压缩,去掉维数为1的的维度,比如是一行或者一列这种,一个一行三列(1,3)的数去掉第一个维数为一的维度之后就变成(3)行。squeeze(a)就是将a中所有为1的维度删掉。a.squeeze(N) 就是去掉a中指定的维数为一的维度。torch.unsqueeze()对数据维度进行扩充。给指定位置加上维数为一的维度,比如原本有个三行的数据(3),在0的位置加了一维就变成一行三列(1,3)。a.squeeze(N) 就是在a中指定位置N加上一个维数为1的维度。torch.transpose() 交换tensor指定的两个维度torch.cat()将几个tensor在指定维度拼接起来指定在GPU上跑:x = x.to('CPU') x = x.to('cuda') GPU可以并行处理算微分:① 定义tensor x = torch.tensor([[1,0],[-1,2]],requires_grad = True) ② 定义函数z = x.pow(2).sum ③ 计算gradientz.backward() ④ x.grad输出微分
Load Data 数据处理: ①需要from torch.utils.data import Dataset, DataLoader ② 定义一个MyDataset类,其中:init 时需要read data & preprocess;定义getitem,len函数 ③ 创建一个MyDataset类,将它丢到DataLoader中dataloader = DataLoader(dataset, batchsize, shuffle=True);会返回mini-batch(多次调用_getitem_函数得到)
建立NN- fully-connected Layer:nn.Linear(in_features, out_features) 定义输入维度和输出维度;可以查看w和b的维度:layer = torch.nn.Linear(32,64)weight维度:layer.weight.shape Bias维度:layer.bias.shape (官方文档:
y
=
x
W
T
+
b
y=xW^T+b
y=xWT+b)激活函数:nn.Sigmoid() nn.ReLU()Loss Function:nn.MSELoss() nn.CrossEntropyLoss()建立NN:定义MyModel类,包括模型初始化、定义layer(可以用nn.Sequential)self.net = nn.Sequential(xxx);foward:根据刚刚定义的计算output return self.net(x)torch.optim:用于更新model torch.optim.SGD(params, lr, momentum=0)
- 建立dataset类,设置DataLoader,设置在什么设备上运行to(device),损失函数是什么,如何优化。
存/加载模型:torch.save(model.state_dict(),path) ckpt = torch.load(path) model.load_state_dict(ckpt)
- output = torch.max(input, dim): dim是max函数索引的维度0/1,0是每列的最大值,1是每行的最大值;函数会返回两个tensor,第一个tensor是每行的最大值;第二个tensor是每行最大值的索引。判断能否使用GPUtorch.cuda.is_available()str.format()就是把format后面的内容填入大括号
print('a,b,c,{}'.format('d'))
a,b,c,d
- pred.detach().cpu() 阻断反向传播;计算每个epoch得到的模型的训练效果,csv.reader()返回一个reader对象,利用该对象遍历csv文件中的行在python中创建类后,通常会创建一个__ init__ ()方法,这个方法会在创建类的实例的时候自动执行。 其必须包含一个self参数,而且要是第一个参数。super(Net, self).init():子类把父类的__init__()放到自己的__init__()当中,这样子类就有了父类的__init__()的那些东西getattr() 函数用于返回一个对象属性值
- 维度:dim=0代表行,dim=1代表列;代表跨行求值,并不是按行求哦!记住dim=0,就是纵向压缩,代表减少0维。dim=1代表横向压缩。另一种理解只有dim指定的维度是可变的(类似于消融实验),其他都是固定不变的;dim = 0,指定的是行,那就是列不变;dim=1:指定列,也就是行不变,列之间的比较。
myseed = 42069 # set a random seed for reproducibility
# 设置随机数种子固定 每次返回的卷积算法将是确定的
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
# 确保每次运行.py文件时,生成的随机数都是固定的
np.random.seed(myseed)
torch.manual_seed(myseed)
if torch.cuda.is_available():
torch.cuda.manual_seed_all(myseed)
其中设置 torch.backends.cudnn.benchmark=True 将会让程序在开始时花费一点额外时间,为整个网络的每个卷积层搜索最适合它的卷积实现算法,进而实现网络的加速。
实例变量和类变量实例化变量要实例化后用,只属于这个实例。类变量可以直接调用类,并且修改后,实例化后就是修改后的值。
matplotlib- T10调色盘适用于离散分类,其颜色名称以tab:为前缀。plt.xlim(xmin,xmax)设置上下限步骤:① 导入from matplotlib.pyplot import figure ②plt.figure(figsize=(4, 3))指定画布大小 ③ 处理好数据,调用plot函数 ④ 设置x y轴上下限
- 创建新类(继承dataset类),加载数据 class XXDataset(Dataset),包括__init__ 读取数据(注意,训练集测试集验证集的data是不同的,分开写的;target和data也是这个地方分出来的), __getitem__ 返回数据,__len__返回长度。之后需要创建dataset对象,并传入dataloader实例化dataset,创建DataLoader对象。需要传入dataset和batchsize,shuffle(True/False)
dataloader = DataLoader(
dataset, batch_size,
shuffle=(mode == 'train'), drop_last=False,
num_workers=n_jobs, pin_memory=True)
Dataset是一个包装类,用来将数据包装为Dataset类,然后传入DataLoader中。DataLoader为我们提供的常用操作有:batch_size(每个batch的大小), shuffle(是否进行shuffle操作), num_workers(加载数据的时候使用几个子进程) 建立神经网络:
- class NeuralNet(nn.Module) 继承父类,初始化函数中:建立神经网络self.net = nn.Sequential(),评价指标self.criterion = nn.MSELoss(reduction='mean')注意:一定要传入的参数:input_dim(输入维度输出维度)定义forward(计算网络输出的)和cal_loss函数(c直接代入前面定义的riterion函数)后面创建model对象后调用model(x)就是在运行forward函数;之后调用model.cal_loss计算损失;再计算微分,进行更新mse_loss.backward() optimizer.step()
- 先定义优化器optimizer算损失,并反向传播mse_loss.backward() optimizer.step()
optimizer.zero_grad() loss.backward() optimizer.step()
- 需要传入的参数:tr_set(dataloader对象), model, device 数据集、模型、运行设备;之后需要规定训练模式 model.train() 评估:model.eval()dataloader模型可以迭代使用for x, y in tr_set
while epoch < n_epochs:
model.train() # set model to training mode
for x, y in tr_set: # iterate through the dataloader
optimizer.zero_grad() # set gradient to zero
x, y = x.to(device), y.to(device) # move data to device (cpu/cuda)
pred = model(x) # forward pass (compute output)
mse_loss = model.cal_loss(pred, y) # compute loss
mse_loss.backward() # compute gradient (backpropagation)
optimizer.step() # update model with optimizer
loss_record['train'].append(mse_loss.detach().cpu().item())
整体流程:
- 创建DataLoader实例,传入数据集、mode、batchsize等参数tr_set = prep_dataloader(tr_path, 'train', config['batch_size']),返回一个实例。创建model并放到device上model = NeuralNet(tr_set.dataset.dim).to(device)调用train函数训练model_loss, model_loss_record = train(tr_set, dv_set, model, config, device)(传入的都是dataloader对象,会在train中进行遍历for x, y in tr_set),其中,每运行一次epoch更新一次参数,就要运行一次验证集查看效果;当验证集上的loss小于阈值,说明有效,保存模型torch.save(model.state_dict(), config['save_path'])加载刚刚训练好的模型,在验证集上加载看效果。
ckpt = torch.load(config['save_path'], map_location='cpu') # Load your best model model.load_state_dict(ckpt) plot_pred(dv_set, model, device) # Show prediction on the validation set
- 在测试集运行,并保存结果:plot_pred(dv_set, model, device) preds = test(tt_set, model, device)
- os.makedirs(path,mode) 方法用于递归创建目录torch.FloatTensor将list ,numpy转化为tensormean(dim=0, keepdim=True)运算完之后的维度和原来一样判断向量维度:先看起始位置有几个中括号就代表几维。然后去掉一组中括号,数最外圈剩下多少对[];之后依次去掉中括号。x=[[[1,2,3],[4,5,6],[1,1,1],[2,2,2]]]3维,143; x=[[1,2,3],[4,5,6],[1,1,1],[2,2,2]]2维数组,4*3早停法:当模型在验证集上的表现开始下降的时候,停止训练,这样就能避免继续训练导致过拟合的问题。测试集和验证集上做实验时要加上with torch.no_grad()model.train()(启用 Batch Normalization 和 Dropout。)和model.eval()(不启用 Batch Normalization 和 Dropout。)的区别主要在于Batch Normalization和Dropout两层。如果模型中有BN层(Batch Normalization)和Dropout,需要在训练时添加model.train(),在测试时添加model.eval()。其中model.train()是保证BN层用每一批数据的均值和方差,而model.eval()是保证BN用全部训练数据的均值和方差;而对于Dropout,model.train()是随机取一部分网络连接来训练更新参数,而model.eval()是利用到了所有网络连接。
- learn的过程,求梯度 更新
self.optimizer.zero_grad()
loss.backward()
self.optimizer.step()
- torch.nn.functional 包里有卷积函数torch.nn.functional.conv1d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1),池化函数,激活函数torch.nn.functional.softmax(input)Categorical(probs) 作用是创建以参数probs为标准的类别分布
- 每个变量都有两个标志:requires_grad和volatile。它们都允许从梯度计算中精细地排除子图,并可以提高效率。requires_grad说明当前Variable变量是否需要在计算中保留对应的梯度信息。若一个节点requires_grad被设置为True,那么所有依赖它的节点的requires_grad都为True。volatile=True是Variable的另一个重要的标识,它能够将所有依赖它的节点全部设为volatile=True,其优先级比requires_grad=True高。现在用with torch.no_grad()代替!
volatile=True的节点不会求导,即使requires_grad=True,也不会进行反向传播,对于不需要反向传播的情景(inference,测试推断),该参数可以实现一定速度的提升,并节省一半的显存,因为其不需要保存梯度。
- 使用backward()函数反向传播计算tensor的梯度时,并不计算所有tensor的梯度,而是只计算满足这几个条件的tensor的梯度:1.类型为叶子节点、2.requires_grad=True、3.依赖该tensor的所有tensor的requires_grad=True。torch.nn.Parameter() Parameter不能被 volatile(即:无法设置volatile=True)而且默认requires_grad=Truetorch.nn.Module是所有network的基类,所有network都要继承它forward()在所有的子类中都需要重写这个函数。卷积层class torch.nn.Conv1d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)池化层torch.nn.MaxPool1d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False) 池化层夹在连续的卷积层中间, 用于压缩数据和参数的量,减小过拟合。激活函数:nn.ReLU() nn.Softmax() nn.Sigmoid() nn.Tanh()标准化:torch.nn.BatchNorm1d(num_features, eps=1e-05, momentum=0.1, affine=True)BatchNorm就是在深度神经网络训练过程中使得每一层神经网络的输入保持相同分布的。 num_features就是你需要归一化的那一维的维度。
nn.BatchNorm1d本身不是给定输入矩阵,输出归一化结果的函数,而是定义了一个方法,再用这个方法去做归一化。
- 循环网络:nn.RNN() nn.LSTM() nn.GRU()Dropout: torch.nn.Dropout(p=0.5, inplace=False)Sparse: torch.nn.Embedding(num_embeddings, embedding_dim, padding_idx=None, max_norm=None, norm_type=2, scale_grad_by_freq=False, sparse=False) 一个保存了固定字典和大小的简单查找表。Distance : torch.nn.PairwiseDistance(p=2, eps=1e-06)Loss: nn.L1Loss() nn.MSELoss() nn.CrossEntropyLoss()优化器:为了构建一个Optimizer,你需要给它一个包含了需要优化的参数(必须都是Variable对象)的iterable。然后,你可以设置optimizer的参 数选项,比如学习率,权重衰减,等等。optimizer = optim.Adam([var1, var2], lr = 0.0001)optimizer.step()实现单次优化
- torch.from_numpy(ndarray)从numpy.ndarray创建一个张量del codes, indexes 删除输出, gc.collect() 清理内存。torch.max(input, dim)返回两个tensor,第一个tensor是每行的最大值;第二个tensor是每行最大值的索引。常常用于分类任务torchvision是pytorch的一个图形库,它服务于PyTorch深度学习框架的,主要用来构建计算机视觉模型。torchvision.transforms.Compose()类。这个类的主要作用是串联多个图片变换的操作
每次看都会记不清楚,那就看一次记录一次好了
- class TIMITDataset(Dataset)创建dataset类。里面定义了三个函数,def __init__(), def __getitem__(), def __len__(self)(相当于重写了dataset类)。train_set = TIMITDataset(train_x, train_y) 实例化dataset类train_loader = DataLoader(train_set, batch_size=BATCH_SIZE, shuffle=True)传入DataLoader(刚刚实例化的dataset,batchsize,shuffle取值)class Classifier(nn.Module)创建模型,继承nn.Module。定义了两个函数def __init__(self):定义了网络结构; def forward(self, x):给定输入x,如何输出。实例化模型并放到device上model = Classifier().to(device),定义衡量指标criterion = nn.CrossEntropyLoss()和优化器optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)。开始训练,从dataloader中取值,并把数据放到device上(输入值和真实值);一开始需要设置梯度为0,然后计算损失,进行反向传播
for i, data in enumerate(train_loader):
inputs, labels = data
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
batch_loss = criterion(outputs, labels)
_, train_pred = torch.max(outputs, 1) # get the index of the class with the highest probability
batch_loss.backward()
optimizer.step()
- 验证/测试时,要设定model.eval() 设置不计算梯度with torch.no_grad():
if len(val_set) > 0:
model.eval() # set the model to evaluation mode
with torch.no_grad():
for i, data in enumerate(val_loader):
inputs, labels = data
inputs, labels = inputs.to(device), labels.to(device)
outputs = model(inputs)
batch_loss = criterion(outputs, labels)
_, val_pred = torch.max(outputs, 1)
val_acc += (val_pred.cpu() == labels.cpu()).sum().item() # 分类任务
val_loss += batch_loss.item()
print('[{:03d}/{:03d}] Train Acc: {:3.6f} Loss: {:3.6f} | Val Acc: {:3.6f} loss: {:3.6f}'.format(
epoch + 1, num_epoch, train_acc/len(train_set), train_loss/len(train_loader), val_acc/len(val_set), val_loss/len(val_loader)
))
类与继承
- IterativeRecommender继承Recommender父类,super(IterativeRecommender, self).__init__(conf,trainingSet,testSet,fold)是给父类的初始化函数传参。
class IterativeRecommender(Recommender):
def __init__(self,conf,trainingSet,testSet,fold='[1]'):
super(IterativeRecommender, self).__init__(conf,trainingSet,testSet,fold)
VirtualTaobao代码
创了一个virtualTaobao env环境,里面包含了render, step()等函数
- collections.namedtuple(typename, field_names, verbose=False, rename=False) 具有名字的元组。User = collections.namedtuple('User', 'name age id')apply和weight_init函数 可以对多层网络做初始化装饰器:加了@property后,可以用调用属性的形式来调用方法浅拷贝 深拷贝



