引言

当我们在学习和研究深度学习时,需要经常对参数进行调整,有的需要通过命令行的方式进行修改,有的则可以作为固定参数放在程序中。其中对于那种需要在运行程序时选择模式或者命名等只有在运行程序时才确定的参数一般采用命令行输入的方式确定;对于那些训练过程中一定需要的参数,我们可以通过将其写在程序中,来使其发挥作用。这是我们设置参数部分,当然对于一些我们曾经训练过的模型,我们可以首先将模型保存,然后当再训练的时候,根据不同的指标,选取不同的模型,开始训练。今天我们就来讲解下深度学习过程中会用到的参数设置以及模型导入的小技巧。

参数设置

这里我们介绍两种参数设置方法,一种是通过python模块进行设置,它可以让我们使用命令行进行参数设置;另一种是通过新建专门存放参数的文件来解决。

argparse

这个模块就是可以用来实现从命令行获取参数的作用,在使用时我们使用import进行导入就可以。

import argparse

在使用时,我们首先需要设置一个解析器对象,也就是说。我们是通过设置一个解析器对象,然后定义解析器中需要由的参数,这里不同的参数的定义方法不同,后面会有介绍,最后在程序中调用这个对象中的参数就可以得到其对应的值,解析器对象的定义方式如下:

parser = argparse.ArgumentParser(description='这里写解析器名称,这一项可有可无')

那这一项我们怎么使用呢?

当你把程序打包放到pypi或者是一个完全不熟悉你程序的人想要运行你的代码,那他首先需要知道你的解析器的设置是什么样的,以及一些关于这个程序你需要了解的东西。argparse提供了-h命令,让我们可以获取到这个解析器的描述。

对了我们还没有介绍这个解析器怎么用。

当我们想要使用解析器进行参数设置的时候,可以使用

python xxx.py -[ ] -[ ] ...

进行设置,或者查看。比如上面提到的-h,我们就可以这样使用:

python xxx.py -h

j接着,终端中就会输出这样的字眼:

我们可以看到其他还有一些-[ ]可以去设置,对,那些就是我自己设置的。

自己设置的参数可以分为赋值形和bool型。

对于赋值型的参数,我们可以一般通过如下两种的方式进行设置:

1、可有可无

parser.add_argument("-n", required=True, help="Name of the run")

2、必须存在

parser.add_argument('--lr', type=float, help='learning rate', default=0.0001)

对于可有可无的参数,我们需要设置required-False,这样就算命令行中没有设置这个参数也不会报错,而另一种设置了默认值,当你在命令行没有设置这个参数的时候,他就会填充默认值。

在-还是--这个问题上,一般情况下-和--都可以,这时我们只需要在执行程序的时候写对就可以,比如在程序里写-n,那在执行python xxx.py的时候后面跟着的也就是-n。但是打当我们在程序里有个参数,由于在定义的时候按照含义定义的,所以可能很长,为了方便起见需要设置一个简写的,这时,可以这样设置:

parser.add_argument("-n", "-name",required=True, help="Name of the run")

这个时候n就是name的面向命令行的时候的代替的简写了,我们可以使用-n或者--n来跟后面需要的参数。但是注意,这个简写一定是原来长变量的首字母才可以实现-n和--n都可以的效果!

对于bool型的变量:

    parser.add_argument("--test", default=False, action='store_true', help='Enable test mode')

注意这里的default里的false就是默认为false,action里的store_store就是变为true的意思,也就是说,当我们在定义参数的时候加上这个参数,就表示其值为true。

PARAMS.py

这个名字可以随便起,其核心思想就是,我们定义一个参数文件,在这个文件里,我们使用python自带的字典对参数进行设置,然后在用到它的地方import一下,使用的时候这样用就可以:

PARAMS['BATCH_SIZE']

我的定义如下:

PARAMS = {
'GAMMA':             0.93,
'REWARD_STEPS':      1,
'BATCH_SIZE':        12,
'seq_state':         15,
'LEARNING_RATE':     3e-5,
'ENTROPY_BETA':      1e-6,
'TEST_ITERS':        4,
'zige':              0.75,
'second_model':      200,
'thrid_model':       400,
'zige_len':          100,
}

模型导入

在模型导入部分,我们可以根据不同的指标进行导入,这里其实最重要的就是首先需要对模型文件按照我们想要的指标进行排序,然后从中选择我们想要的文件。比如在这个程序中:

def continue_train(name,net,reload = False):
    filelists = os.listdir(f'{dirr}/saves/{name}')
    sort_num_first = []
    best_reward = 0
    for file in filelists:
        sort_num_first.append(int(float(file.split("_")[2].split(".")[0])))
        sort_num_first.sort()
        sort_num_first.sort(key=None)
    sorted_file = []
    for sort_num in sort_num_first:
        for file in filelists:
            try:
                if str(sort_num) == file.split("_")[2].split(".")[0]:
                    sorted_file.append(file)
                    best_reward = float(file.split("_")[1])
            except:
                print("有内鬼,终止交易1")
    if reload==False:
        try:
            net.load_state_dict(torch.load(f'{dirr}/saves/{name}/{sorted_file[-1]}'))
            with open('training_record{}.txt'.format(name), 'a+') as f:
                f.write(str(sorted_file[-1]).replace('(', '').replace(')', '') + ',')
                f.write('\r\n')
            print("导入最佳奖励参数{best_reward}".format(best_reward = sorted_file[-1]))
            print(best_reward)
        except:
            with open('training_record{}.txt'.format(name), 'a+') as f:
                f.write(str("还没有保存的模型").replace('(', '').replace(')', ''))
                f.write('\r\n')
            print("还没有保存的模型")
            best_reward = None
    else:
        try:
            filelists = os.listdir(f'{dirr}/saves/{name}')
            sort_num_first = []
            best_reward = 0
            for file in filelists:
                sort_num_first.append(int(float(file.split("_")[1])))
                sort_num_first.sort()
                sort_num_first.sort(key=None)
            sorted_file = []
            for sort_num in sort_num_first:
                for file in filelists:
                    try:
                        if str(sort_num) == file.split("_")[1]:
                            sorted_file.append(file)
                            best_reward = float(file.split("_")[1])
                    except:
                        print("有内贵,终止交易2")
            net.load_state_dict(torch.load(f'{dirr}/saves/{name}/{sorted_file[-1]}'))
            with open('training_record{}.txt'.format(name), 'a+') as f:
                f.write(str(sorted_file[-1]).replace('(', '').replace(')', '') + ',')
                f.write('\r\n')
            print("导入最佳步长{best_reward}".format(best_reward = sorted_file[-1]))
        except:
            print("有内鬼,终止交易3")
    return best_reward

在这里用reload表示要提取的最优参数是按照模型中哪个指标进行排序,例如在这个任务中,我默认是按照第2个数字大小进行排序,就是奖励值大小。当然我们也可以换第一个数字,进行排序,这时候只需要将reload参数设置为True即可。这是程序就会从我们保存的路径中寻找我们想要的参数。

这个操作可以完成两个目标, 第一个就是之前所说的,可以在中断训练后,重新训练时不用从头开始,直接使用上次训练的模型接着训练就可以;第二个骚操作是,当训练过程中,模型一直不收敛,特别是在强化学习中,如果出现这个问题的时候,我们可以选取次优的参数重新训练,或者使用另一个指标的最优值重新训练。