- 序列标注任务,或者说是基于bert的任务,尽量手动convert_tokens_to_id,如果使用encode_plus可能在处理数据时产生错误。比如序列标注任务时,在语句中添加的[CLS]和[SEP]后,标签可能会和原句不对齐
- tokenizer.tokenize(some_word)返回的结果是列表,可以使用list.extend将返回结果写入tokens : list 中
- 变长padding,感觉可以在get_examples阶段进行。读取所有数据后先根据长度排序后再返回。
- lens=[所有数据长度],len_index = np.argsort(lens),然后data_list = data_list[index]即可,让-1*lens见鬼去吧。
- 在collate_fn之前要先处理好数据长度问题,如果数据长度超过max_length这里也没办法处理。因为到collate_fn的时候已经加好了[CLS]和[SEP],不能使用截断操作了。
- TorchCRF的crf的是有mask参数的,mask=attention_mask.byte()就有作用了。
- list.extend(tokenizer.unk_token) 会添加’[‘, ‘U’, ‘N’, ‘K’, ‘]’,但是extend([tokenizer.unk_token])则添加的是”[UNK]”
- torch.nn.utils.RNN.pack_padded_sequence
原文链接:https://www.cxyzjd.com/article/kejizuiqianfang/100835528
假设存在两条数据:输入RNN的其实是[1,2],[2,3],[3,4],[4,5],[5,6],[6,7],[7,0],最终输入模型的0并非真实数据,若参与运算则会影响模型效果且浪费算力,于是使用torch.utils.nn.RNN.pack_padded_sequence方法(后称“pack”)去除掉输入进模型的padding标记,上述两条数据pack之后得到的结果为:1
2tensor([[1, 2, 3, 4, 5, 6, 7],
[2, 3, 4, 5, 6, 7, 0]])暂且只看第一条数据,pack后的数据为:[1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7],实际上就是去除掉两条数据中padding标记的结果,RNN通过batch_sizes中的数字决定每次输入模型“几个数”,这里的batch_sizes为tensor([2, 2, 2, 2, 2, 2, 1]),意为连续取6次两位数,在第7次时只取一个数。1
2
3
4PackedSequence(data=tensor([1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7]), batch_sizes=tensor([2, 2, 2, 2, 2, 2, 1]), sorted_indices=None, unsorted_indices=None)
PackedSequence(data=tensor([3, 4, 4, 5, 5, 6, 6, 7, 7]), batch_sizes=tensor([2, 2, 2, 2, 1]), sorted_indices=None, unsorted_indices=None)
PackedSequence(data=tensor([5, 6, 6, 7, 7]), batch_sizes=tensor([2, 2, 1]), sorted_indices=None, unsorted_indices=None)
PackedSequence(data=tensor([7]), batch_sizes=tensor([1]), sorted_indices=None, unsorted_indices=None)
- Python中的矩阵乘法
Python中,星乘(*)指两个矩阵对应位置相乘;点乘(.dot)指数学上的矩阵乘法。
在进行星乘时,Python会对“低维度的矩阵”进行广播操作,使之能与另一矩阵维度匹配,而后进行对应位置相乘。1
2
3
4
5
6
7
8
9
10
11
12#假设现有一文本序列
seq = torch.tensor(np.random.randint(0,2,(batch,seq_len)))
#以及该序列所对应的词向量矩阵
vector_mat = torch.tensor(np.random.randn(batch,seq_len,dim))
#现要对padding的部分做mask
mask = seq.unsqueeze(-1)
mask = torch.tensor(mask>torch.tensor(np.array([0])),dtype=torch.float)
print(seq)
print("**********")
print(mask)
print("**********")
print(vector_mat * mask)
- plt.subplots
如果想要创建多个子图,可以使用plt.subplots方法创建“画布”。1
2
3
4
5
6
7
8
9
10
11
12
13
14from matplotlib import pyplot as plt
#设置一块 2*2 的画布,figsize设置子图?整个画布?的尺寸
f,ax = plt.subplots(nrows=2,ncols=2,figsize=(18,12))
#此时ax是一个多维的变量,可以通过flatten变成普通list索引访问
ax = ax.flatten()
#假设此时要画3个hist,可是定义的画布是2*2的,也就是可以画4个图,最后一个会显示空白
ax[0].hist(train_text_lens)
ax[0].set_title("train_text_lens")
ax[1].hist(dev_text_lens)
ax[1].set_title("dev_text_lens")
ax[2].hist(test_text_lens)
ax[2].set_title("test_text_lens")
#想要删除某个子图可以使用plt.delaxes方法
plt.delaxes(ax[-1])
- AutoTokenizer
项目中AutoTokenizer较为常见,与特定的Tokenizer(类似于BertTokenizer)的区别在于,直接使用特定Tokenizer时,cache路径下不需要包括tokenizer.json文件。但是如果使用AutoTokenizer,cache中需要包含的就不仅仅是vocab、model.bin、config.json三个文件了,还需要一个类似于tokenizer.json的文件。
1 | import re |
- json.load()和json.loads()的区别
json.loads()将字符串读取成Python数据结构,json.load()将文件读取成Python数据结构
另外,如果键值对中包含整型数据,将其保存为json后,会将所有的数据转化为字符串。可以使用object_hook参数来解决这个问题。1
2
3
4
5
6
7
8
9
10import json
path = "something/something.json"
def jsonKey2int(x):
if isinstance(x,dict):
return {int(k) : v for k,v in x.items()}
return x
with open(path,encoding="utf-8") as f:
json.load(f,obgject_hook=jsonKey2int) - pytorch中nn.CrossEntropyLoss()的计算过程中是包含Softmax
如果在模型forward过程中自己计算softmax然后再使用交叉熵很可能会导致loss不下降
@生命奇点_ZRY 用交叉熵完成分类任务,线性层的输出可别softmax了喔
- 引包
小项目的工作路径中直接包含若干python文件或包,编写代码时可以直接调用。如果项目规模较大,在工作路径中包含若干子项目时,可能会涉及到不同包下模块的引用,经常会出现无法引用自己写的块的问题。–project
—-main.py
—-folder1
– – test1.py
– – test3.py
—-folder2
– – test2.py
– – test4.py
最外层文件夹名称project,包含main.py和文件夹folder1、folder2。folder1中包含test1.py和test3.py,folder2中包含test2.py和test4.py。
想要正常import,模块必须在sys.path中能被找到,import的查找顺序为:
- 内置模块
- .py文件所在目录(当前工作路径)
- 环境变量中列出的目录(虚拟环境)
- pip 或 easy_install安装的包
可以通过打印sys.path的方式查看当前.py文件中sys.path包含了哪些内容假设当前执行test1.py,打印其sys.path,可以发现folder1是在其中的,此时若需要引用folder2中的模块,那必然是会报错的,但是由于Pycharm等IDE可将floder2设置为source root则可以避免报错,使用cmd执行时就会报错。1
2
3import sys
for i in sys.path:
print(i)
如何解决?
- sys.path.append(“..”)
想要调用父级目录中的模块时,可以将父级目录添加到sys.path中。from 父级目录.folder_name import module
这样就可以通过上述方式引用调用模块。