zoukankan      html  css  js  c++  java
  • 4-3日学习笔记

    1.接bert的pooled_output输出

    https://cloud.tencent.com/developer/article/1588634 这里面提到是不是那个encoded_layers输出,而是第二项输出,但我之前接LSTM都是直接的第一个输出,也就是每个单词的输出,难道就是只接pooled_output效果会更好吗?

    但是我又觉得,如果是这样的话,那么lstm的一个参数seq_length就全部为1吗?那这样就是说time_step为1?这样真的能够学的有效吗? 

    我还是不太明白,先搁置https://github.com/bentrevett/pytorch-sentiment-analysis/blob/master/6%20-%20Transformers%20for%20Sentiment%20Analysis.ipynb ,这里面给的教程明明是使用的第0个输出,把它当作了bert的emb,然后输入进GRU,所以使用encoded_layers看起来并没有什么毛病?

    2.pytest包

    python中可以用来测试的包?算了,以后再说,现在用不到。

    3.for((i=0;i<5;i++));  

    https://www.sololearn.com/Discuss/1725255/why-does-this-exist-for-int-i-0-i-5-i

    This kind of loop can be use to create a delay / pause in you program...

    主要就是delay的作用。

    我又知道了,在shell脚本中,它是进行for循环的意思。。。

    4.gradient_accumulation_steps

    2020-5-2更新—————— 

    https://linux.ctolib.com/guoday-CCF-BDCI-Sentiment-Analysis-Baseline.html,这里提到:

     主要就是为了解决显存小的问题,这样就会默认降低batch_size了,真实的bs=bs/gas,每gas计算一次梯度,累计到bs后更新。

    args.train_batch_size = args.train_batch_size // args.gradient_accumulation_steps

    这句在训练bert时的代码就可以看出来,bs进行了更新。

            num_train_optimization_steps = int(
                len(train_examples) / args.train_batch_size / args.gradient_accumulation_steps) * args.num_train_epochs

    注意:有的实现的地方,num_train_optimization_steps 等号右边没有/args.train_batch_size,所以就是计算方式有所不同,还是看具体的项目中是如何实现的吧。

    除或者不除bs,关乎到gas是否可以大于bs。

    在simpletransformer的分类模型中,是这么来用的:

            train_dataloader = DataLoader(train_dataset, sampler=train_sampler, batch_size=args["train_batch_size"])
    
            t_total = len(train_dataloader) // args["gradient_accumulation_steps"] * args["num_train_epochs"]

    假设len(train_examples)=128,train_batch_size=4,gradient_accumulation_steps=8,epoch=3,

    那么total=128//8*3=48。而在上面的train_dataloader ,仍是以原来的bs加载的数据。

                    if args["gradient_accumulation_steps"] > 1:
                        loss = loss / args["gradient_accumulation_steps"]

    在train中,loss/8,其实不是很明白上面为什么要loss/gas呢???难道/了之后计算所需的内存就会变小?

    每个batch都将loss/gas,

    /了之后进行backward,和不/有什么区别呢?

    # 每n个batch(把这些batch的梯度求和),更新一次参数 #下面的if。
    ...
    loss.backward()
    if (step + 1) % args["gradient_accumulation_steps"] == 0: torch.nn.utils.clip_grad_norm_(model.parameters(), args["max_grad_norm"]) optimizer.step() scheduler.step() model.zero_grad() ....

    之后反向传播计算损失,当step进行了8次之后才更新参数。

    忽然一点通,loss/gas之后就是为了后面的if时能够一次更新gas个bach的。

    那还有个问题,在训练的时候主要的内存占用是反向传播在求loss,还是在更新参数的时候呢?

    5.dataframe.fillna(inplace)参数

    https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.fillna.html 这里是说,

    如果在填充时设置为True的话,那么会改变其他非copy的切片列,这个我不太明白,如果是之前的切片,那就会受到影响?那么如果是fillna之后的切片会受到影响吗?

    import pandas as pd
    import numpy as np
    df = pd.DataFrame([[np.nan, 2, np.nan, 0],
                       [3, 4, np.nan, 1],
                       [np.nan, np.nan, np.nan, 5],
                       [np.nan, 3, np.nan, 4]],
                      columns=list('ABCD'))
    df1=df.iloc[2]
    df=df.fillna('缺失')
    df2=df.iloc[2]
    print(df1)
    print(df2)
    
    #输出:
    A    NaN
    B    NaN
    C    NaN
    D    5.0
    Name: 2, dtype: float64
    A    缺失
    B    缺失
    C    缺失
    D     5
    Name: 2, dtype: object

     可以发现,之前的切片是不会受到影响的,即df1,之后的切片会随之改变即df2,那么fillna时设置inplace=True,结果如下:

    如果是这样:

    df1=df.iloc[2]
    df.fillna('缺失')#注意和上面的差别,这里没有返回
    df2=df.iloc[2]
    print(df1)
    print(df2)
    
    #输出:
    A    NaN
    B    NaN
    C    NaN
    D    5.0
    Name: 2, dtype: float64
    A    NaN
    B    NaN
    C    NaN
    D    5.0
    Name: 2, dtype: float64
    >>> df
         A    B   C  D
    0  NaN  2.0 NaN  0
    1  3.0  4.0 NaN  1
    2  NaN  NaN NaN  5
    3  NaN  3.0 NaN  4

    发现,如果没有inplace的话它应该要再返回一个副本,之后用这个填充后的副本完成剩下的操作,而:

    df1=df.iloc[2]
    df.fillna('缺失',inplace=True)
    df2=df.iloc[2]
    print(df1)
    print(df2)
    
    #输出:
    A    NaN
    B    NaN
    C    NaN
    D    5.0
    Name: 2, dtype: float64
    A    缺失
    B    缺失
    C    缺失
    D     5
    Name: 2, dtype: object
    >>> df
        A   B   C  D
    0  缺失   2  缺失  0
    1   3   4  缺失  1
    2  缺失  缺失  缺失  5
    3  缺失   3  缺失  4

    这样就完全不必再赋值给df,而且之前的切片并不会受影响哦,受到的只是自身和后来切片的影响。而如果想要尝试赋值:

    df1=df.iloc[2]
    df=df.fillna('缺失',inplace=True)
    df2=df.iloc[2]
    print(df1)
    print(df2)
    #输出:
        df2=df.iloc[2]
    AttributeError: 'NoneType' object has no attribute 'iloc'

    说明,=True之后的fillna是不返回内容的。

    2020-4-4周六——————————————

    1.action=store_true参数

    这里到底是什么意思呢?

    https://blog.csdn.net/LemonTree_Summer/article/details/80749359  说了一些但是还是不太明白,这是要存储这个参数吗?那存储到哪里呢?运行完程序我可以在哪里查看呢?

    终于搞明白了,https://www.cnblogs.com/lovemyspring/p/3214598.html 这个讲的真不错。

    例子:

    import argparse
    
    parser = argparse.ArgumentParser(description='Short sample app')
    
    parser.add_argument('-a', action="store_true", default=False)
    parser.add_argument('-b', action="store", dest="b")
    parser.add_argument('-c', action="store", dest="c", type=int)
    
    print parser.parse_args(['-a', '-bval', '-c', '3'])
    #输出:
    Namespace(a=True, b='val', c=3)

    上面中,如果a出现了,那么就设置为True,没有出现则为False:

    print(parser.parse_args(['-bval', '-c', '3']))
    #输出:
    Namespace(a=False, b='val', c=3)

    如果改变a,

    parser.add_argument('-a', action="store_false", default=False)
    。。。
    print(parser.parse_args(['-bval', '-c', '3']))
    #输出:
    Namespace(a=False, b='val', c=3)#还是取决于default了

    如果去掉default,

    parser.add_argument('-a', action="store_false")
    。。。
    print(parser.parse_args(['-bval', '-c', '3']))
    #那么默认就为True了
    Namespace(a=True, b='val', c=3)

    如果改变b,

    parser.add_argument('-b', action="store",dest='bdd')
    。。。
    print(parser.parse_args(['-bval', '-c', '3']))
    #输出:
    Namespace(a=True, bdd='val', c=3)

    可以发现,action=store的话,如果有dest中的变量名设值为这个值,如果没有dest的话,那就将当前-变量设置为这个值。store_false/True就是设置为false还是True

    store_false,出现则为False,不出现为True;store_true则出现为True,不出现为False。终于明白了,我之前还以为store是要把变量存储到文件呢。

    如果不给b参数,

    parser.add_argument('-b', action="store",dest='bdd')
    。。。
    print(parser.parse_args([ '-c', '3']))
    #输出:
    Namespace(a=True, bdd=None, c=3)

    上面可以看出,如果没有b参数的话,就默认为None,

    2.pytorch fp16

    https://blog.csdn.net/britney_f/article/details/89177575讲的还蛮好的,精度降低占用的显存就会变小,但同时好像因为梯度的影响精确度就会下降?

    我还是先不尝试了吧。

    2020-5-2周六更新————————————

    https://discuss.pytorch.org/t/training-with-half-precision/11815,这个是否有人用fp16跑过一些常用模型的问题?

    其中探讨了对bn的影响,“您要确保BatchNormalization图层使用float32进行累加,否则会出现收敛问题。”

    model.half()  # convert to half precision
    for layer in model.modules():
      if isinstance(layer, nn.BatchNorm2d):
        layer.float()

    //但是我目前并不明白为什么要bn单独设置。

    感觉这个帖子里整体是可以用fp16吧。

    https://www.kaggle.com/c/carvana-image-masking-challenge/discussion/37415,这个也探讨了fp16.

    这里的回答说,用fp16反倒在GPU上慢了?它只是为了能够说,使数据占用的内存小从而能够拥有更大的模型。

    3.os.path.join

    import os
    a=os.path.join('./', 'train.csv')
    print(a)
    print(type(a))
    #输出:
    ./train.csv
    <class 'str'>

    使用了这个模块之后,就a还是str类型的,为什么不直接字符串相加呢?我还是感受不到这个join函数的魅力啊。

    4.Syntax error: Bad for loop variable 运行shell文件报错

    https://askubuntu.com/questions/400936/loop-variable-error-in-for-loop 果然还是谷歌了一下靠谱,在shell文件中添加#!/bin/bash即可。

    5.python垃圾回收机制

    https://www.cnblogs.com/franknihao/p/7326849.html 这个有两个讲的不错。

    import sys
    class Test():
      def __init__(self):
        pass
    
    t = Test()
    k = Test()
    t._self = t
    print sys.getrefcount(t)    #sys.getrefcount函数用来查看一个对象有几个引用
    print sys.getrefcount(k)
    ####结果####
    3
    2

    内存泄漏是说,当前内存块已经没有引用指向了,但又没有别的变量指向这个,所以python既无法清理我们也无法访问。

    gc.collect()可以处理循环引用的问题,释放内存。
    import sys
    import gc
    
    a = [1]
    b = [2]
    a.append(b)
    b.append(a)
    ####此时a和b之间存在循环引用####
    print(sys.getrefcount(a))    #结果应该是3
    print(sys.getrefcount(b))    #结果应该是3
    del a
    del b
    ####删除了变量名a,b到对象的引用,此时引用计数应该减为1,即只剩下互相引用了####
    try:
        sys.getrefcount(a)
    except NameError:
         print ('a is invalid')
    ####此时,原来a指向的那个对象引用不为0,python不会自动回收它的内存空间####
    ####但是我们又没办法通过变量名a来引用它了,这就导致了内存泄露####
    unreachable_count = gc.collect()
    ####gc.collect()专门用来处理这些循环引用,返回处理这些循环引用一共释放掉的对象个数。这里返回是2####
    
    #但是我跑了之后输出:
    3
    3
    a is invalid
    >>> unreachable_count
    12
    #居然是12哎,这么多吗?

    https://www.cnblogs.com/kaituorensheng/p/4449457.html

    在Python中,为了解决内存泄露问题,采用了对象引用计数,并基于引用计数实现自动垃圾回

    6./bin/bash^M: 解释器错误: 没有那个文件或目录

    刚跑那个文件,一样的shebang,#!/bin/bash

    OMG,https://blog.csdn.net/u011479200/article/details/79384930 从这里面找到了原因,是因为我是在win下写的shell文件,然后上传到服务器端,会产生换行符的问题,然后用

    cat -A run_combine.sh命令,查看,包括显示换行符,结果如下:

    而查看之前可以正常运行的文件显示如下: 

     可以发现是换行符存在问题,都多了个^M,这是什么鬼。解决:https://blog.csdn.net/netwalk/article/details/14135307

    sed -i 's/
    $//' run_combine.sh

    即可,会对换行符进行处理。修改之后:

  • 相关阅读:
    JS 缓冲运动 带运动的留言本 小案例
    ===>===>===>特色思TERSUS元件学习整理
    TERSUS无代码开发(笔记29)-分页(转载)
    TERSUS无代码开发(笔记28)-英文日期改成中文日期设置
    TERSUS无代码开发(笔记27)-按钮加图标
    TERSUS无代码开发(笔记26)-复杂表格中字体通过逻辑设置颜色
    TERSUS无代码开发(笔记25)-弹窗的样式设置
    TERSUS无代码开发(笔记24)-排序显示和高级查询
    TERSUS无代码开发(笔记23)-数据库字段设置
    TERSUS无代码开发(笔记22)-利用CSS制作一个悬浮子菜单(转载)
  • 原文地址:https://www.cnblogs.com/BlueBlueSea/p/12629830.html
Copyright © 2011-2022 走看看