12.12 日志

北城余情 提交于 2019-12-13 15:30:37

一.Pyramid Feature Attention Network for Saliency detection论文的代码运行

代码:https://github.com/CaitinZhao/cvpr2019_Pyramid-Feature-Attention-Network-for-Saliency-detection

环境需求:TF-1.12 with all other dependencies being latest versions works well for me.

Tensorflow与Keras版本之间的兼容性
https://docs.floydhub.com/guides/environments/
tensorflow1.12+keras2.2.4

Tensorflow版本与cuDNN CUDA的版本配合
https://www.jianshu.com/p/464fefb5c5d8
在这里插入图片描述当前系统环境是 CUDA 8.0 和 CUDNN 6.0
但Tensorflow1.12要求 CUDA 9.0 和 CUDNN 7.0
报错:ImportError: libcublas.so.9.0: cannot open shared object file: No such file or directory

所以要更换CUDA和CUDNN版本

1.卸载旧cuda

卸载原来的cuda8.0(注意:不需要卸载显卡驱动,不要给自己找麻烦):

sudo /usr/local/cuda-8.0/bin/uninstall_cuda_8.0.pl

卸载之后,会发现 /usr/local/cuda-8.0目录下任然有文件存在,这是cudnn文件,所以还需要将cuda-8.0文件删除干净:

sudo rm -rf /usr/local/cuda-8.0
2. 安装cuda9.0

nvidia官网下载对应操作系统的CUDA安装包。
下载cuda9.0的安装文件 cuda_9.0.176_384.81_linux.run
执行如下命令:
接着按下面的步骤选择:
accept
n(不要安装driver)
y
y
y
安装完成。

3.修改环境变量
sudo gedit /etc/profile

将原有的

export PATH=/usr/local/cuda-8.0/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64$LD_LIBRARY_PATH

加注释

另外添加三行

export PATH=/usr/local/cuda-9.0/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64$LD_LIBRARY_PATH
export CUDA_HOME=/usr/local/cuda-9.0

更新环境变量

source ~/.bashrc
4.更换CUDNN版本

1.登录官方网址https://developer.nvidia.com/cuDNN
选择自己需要的版本进行下载,解压出一个名为cuda的文件夹,文件夹中有include和lib64两个文件夹

2.删除原来的cudnn

sudo rm -rf /usr/local/cuda/include/cudnn.h
sudo rm -rf /usr/local/cuda/lib64/libcudnn*

3.安装需要的cudnn.
按照我之前的博客重新安装cudnn即可。

以上部分内容FROM https://www.cnblogs.com/guweixin/p/11134677.html

继续运行代码
报错:ImportError: No module named 'cv2’
安装opencv

pip --default-timeout=1000 install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple

可以运行了~~~~

这篇论文的代码写的特别规整,所以希望好好读读,学习一下。

train.py

os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" 
os.environ["CUDA_VISIBLE_DEVICES"] = "0"

对GPU的调用进行设置:

 # 按照PCI_BUS_ID顺序从0开始排列GPU设备 
 os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
 # 设置当前使用的GPU设备仅为0号设备  设备名称为'/gpu:0'
 os.environ["CUDA_VISIBLE_DEVICES"] = "0"
 #  设置当前使用的GPU设备为0,1号两个设备,名称依次为'/gpu:0'、'/gpu:1'
 os.environ["CUDA_VISIBLE_DEVICES"] = "0,1"
 # 设置当前使用的GPU设备为1,0号两个设备,名称依次为'/gpu:0'、'/gpu:1'。表示优先使用1号设备,然后使用0号设备
 os.environ["CUDA_VISIBLE_DEVICES"] = "0,1"
 # 禁止使用GPU
 os.envion["CUDA_VISIBLE_DEVICES"] = "-1"
#学习率调度器函数,参数是从0开始的epoch,返回一个新的学习率
def lr_scheduler(epoch):
    drop = 0.5  #学习率每次变化为原先的1/2
    epoch_drop = epochs/8.  #希望学习率在所有的epochs里改变8次,即除以8次2,降256倍
    lr = base_lr * math.pow(drop, math.floor((1+epoch)/epoch_drop))
    print('lr: %f' % lr)
    return lr
base_lr = 1e-2
epochs = 50
lr_decay = callbacks.LearningRateScheduler(schedule=lr_scheduler)
callbacks = [lr_decay,modelcheck,tb]
model.fit_generator(traingen, steps_per_epoch=steps_per_epoch,
                        epochs=epochs,verbose=1,callbacks=callbacks)
关于Keras学习率调整:

Keras提供两种学习率适应方法,可通过回调函数实现。
一种是依赖epoch来控制学习率,一种是依赖评价指标是否变化来控制学习率。

1.LearningRateScheduler(schedule)
依赖epoch来控制学习率

参数:
schedule:函数,该函数以epoch号为参数(从0算起的整数),返回一个新学习率(浮点数)。
靠epoch来控制学习率的改变。

这篇文章中写的这个lr_scheduler函数就非常好,可以拿来用。

#学习率调度器函数,参数是从0开始的epoch,返回一个新的学习率
def lr_scheduler(epoch):
    drop = 0.5  #学习率每次变化为原先的1/2
    epoch_drop = epochs/8. 
     #希望学习率在所有的epochs里改变8次,即除以8次2,降256倍。希望在50轮中完成8次降低学习率的操作,所以每隔50/8轮就要降低一次。
    lr = base_lr * math.pow(drop, math.floor((1+epoch)/epoch_drop))
    #math.pow(x,y):求x的y次方。
    #math.floor(x):对x向下取整。
    #上面这行的意思是:0~5轮中,lr=初始学习率×(0.5^0),6~11轮中,lr=初始学习率×(0.5^1),……最后,lr=初始学习率×(0.5^8)。
    print('lr: %f' % lr)
    return lr

设置好初始学习率base_lr ,总共训练的轮数epochs , 每次减小学习率想减小多少倍drop,想在训练中减小几次学习率epochs/8. (减小8次就除以8),其他的不需要改。

2.ReduceLROnPlateau(monitor=‘val_loss’, factor=0.1, patience=10, verbose=0, mode=‘auto’, epsilon=0.0001, cooldown=0, min_lr=0)
依赖评价指标是否变化来控制学习率。
当评价指标不在提升时,减少学习率。
当学习停滞时,减少2倍或10倍的学习率常常能获得较好的效果。该回调函数检测指标的情况,如果在patience个epoch中看不到模型性能提升,则减少学习率。

参数:

monitor:被监测的量
factor:每次减少学习率的因子,学习率将以lr = lr*factor的形式被减少
patience:当patience个epoch过去而模型性能不提升时,学习率减少的动作会被触发
mode:‘auto’,‘min’,‘max’之一,在min模式下,如果检测值触发学习率减少。在max模式下,当检测值不再上升则触发学习率减少。
epsilon:阈值,用来确定是否进入检测值的“平原区”
cooldown:学习率减少后,会经过cooldown个epoch才重新进行正常操作
min_lr:学习率的下限

reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=10, mode='auto')
callbacks = [reduce_lr ,modelcheck,tb]
model.fit(train_x, train_y, batch_size=32, epochs=5, validation_split=0.1, callbacks=callbacks)

之前在我的代码里,用的是这种学习率改变方式,感觉不是特别好用,也有可能是我别的地方设置有问题。
如果用这种的话,一般设置monitor,factor,patience就可以了。

if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser(description='Train model your dataset')
    parser.add_argument('--train_file',default='train_pair.txt',help='your train file', type=str)
    parser.add_argument('--model_weights',default='model/vgg16_no_top.h5',help='your model weights', type=str)

    args = parser.parse_args()
    train_path= args.train_file
    '''
    the from of 'train_pair.txt' is 
    img_path1 gt_path1\n
    img_path2 gt_path2\n 
    '''
    model_name = args.model_weights
    
    print("train_file", train_path)
    print("model_weights", model_name)

argparse模块

argparse是一个Python模块:命令行选项、参数和子命令解析器,可以让人轻松编写用户友好的命令行接口。程序定义它需要的参数,然后 argparse 将弄清如何从 sys.argv 解析出那些参数。 argparse 模块还会自动生成帮助和使用手册,并在用户给程序传入无效参数时报出错误信息。

简单点来说,就是可以通过它让用户在命令行自定义一些参数。

使用它需要四步:

1.创建ArgumentParser 对象。

import argparse
parser = argparse.ArgumentParser(description='一些描述')

2.添加参数。

parser.add_argument('--train_file',default='train_pair.txt',help='your train file' , typr=str)
parser.add_argument('--参数名', default='默认值',help='提示文字',typr=参数类型)

3.解析参数。

args=parser.parse_args()

4.使用参数

train_path = args.train_file

定义一个优化器

1.SGD优化器

 optimizer = optimizers.SGD(lr=base_lr, momentum=0.9, decay=0)

参数:

  • 学习率
  • 动量 momentum=0.9
    参数更新动量,大或等于0的浮点数,我看所有网上博客的动量设置的都是0.9
  • decay
    float >= 0. 学习率每次更新的下降率
    如果自己设置了学习率调整函数,则把它设成0

2.Adam优化器(参数推荐使用默认值)

optimizer = optimizers.Adam(lr=base_lr)

本质上是 RMSProp 与动量 momentum 的结合,通常是训练循环神经网络RNN的不错选择。

目前在显著性模型的训练中,只见过这两种优化器。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!