文章心中无码便是高清,马赛克“脑补”算法 PULSE
一、万恶马赛克万恶的马赛克,是阻碍人类进步的绊脚石。马赛克“脑补”算法 PULSE,助你图片模糊变高清。 这是杜克大学近期的一项研究,将模糊人脸秒变高清。PULSE 算法目前只支持人脸的马赛克“去除”,因为训练数据都是人脸。 也就是说,“脑补”其它物体马赛克下的内容也是可以的,只要你有数据! 我知道,你一定又有了一些大胆的想法! 「 Just do it 」 !今天,继续手把手教学。 算法原理、环境搭建、效果测试,一条龙服务,尽在下文! 二、算法原理PULSE 算法可以在几秒内,将 16x16 像素的低分辨率(Low Resolution,以下简称 LR)小图,放大 64 倍,变成 1024 x 1024 像素的高分辨率(High Resolution,以下简称 HR)图像。 PULSE 算法会「脑补」出 LR 图像一些不存在的特征,补充细节,例如纹理、毛孔、毛发等:左图为原始 LR 图片,右图为 PULSE 算法生成的 HR 图片。 PULSE 算法的思路是,拿到一张 LR 图片,使用 stylegan 生成 HR 图片,再将 HR 图片 downscale 得到的 LR 图片与原始 LR 图片对比,一直迭代收敛,找到最接近的那张。如下图所示:原始 LR 图片和 PULSE 修复后再 donwscale 的 LR 图片对,使两者最接近的 HR 图片,就是修复得到的 HR 图片。 该算法在著名的高分辨率人脸数据集 CelebA HQ 上进行了效果评估,用 64×,32× 和 8× 的比例因子,采用不同的算法,进行了对比实验。 实验表明,PULSE 算法的效果最佳,得分几乎与真实的高质量照片一样高。 通过上图,可以清晰地看到,PULSE 算法在人脸不同位置的纹理细节。 不过 PULSE 算法也有一定的局限性,它无法将失焦、不能识别的人脸照片,变成照片真人的清晰图像,它仅会生成不存在但看上去很真实的新面孔。 说白了,PULSE 生成的高清图片,是「脑补」出来的,与真实的人脸照片可能存在差别。 三、环境搭建PULSE 算法采用 Pytorch 实现,使用了 dlib 人脸库的一些 API。 项目地址:https://github.com/adamian98/pulse 环境搭建不复杂,工程里的 pulse.yml 文件,已经写明了依赖环境。 name: pulse channels: - pytorch - defaults dependencies: - blas=1.0=mkl - ca-certificates=2020.1.1=0 - certifi=2020.4.5.1=py38_0 - cffi=1.14.0=py38hc512035_1 - chardet=3.0.4=py38_1003 - cryptography=2.9.2=py38ha12b0ac_0 - cycler=0.10.0=py38_0 - freetype=2.9.1=hb4e5f40_0 - idna=2.9=py_1 - intel-openmp=2019.4=233 - jpeg=9b=he5867d9_2 - kiwisolver=1.2.0=py38h04f5b5a_0 - libcxx=10.0.0=1 - libedit=3.1.20181209=hb402a30_0 - libffi=3.3=h0a44026_1 - libgfortran=3.0.1=h93005f0_2 - libpng=1.6.37=ha441bb4_0 - libtiff=4.1.0=hcb84e12_0 - matplotlib=3.1.3=py38_0 - matplotlib-base=3.1.3=py38h9aa3819_0 - mkl=2019.4=233 - mkl-service=2.3.0=py38hfbe908c_0 - mkl_fft=1.0.15=py38h5e564d8_0 - mkl_random=1.1.0=py38h6440ff4_0 - ncurses=6.2=h0a44026_1 - ninja=1.9.0=py38h04f5b5a_0 - numpy=1.18.1=py38h7241aed_0 - numpy-base=1.18.1=py38h6575580_1 - olefile=0.46=py_0 - openssl=1.1.1g=h1de35cc_0 - pandas=1.0.3=py38h6c726b0_0 - pillow=7.1.2=py38h4655f20_0 - pip=20.0.2=py38_3 - pycparser=2.20=py_0 - pyopenssl=19.1.0=py38_0 - pyparsing=2.4.7=py_0 - pysocks=1.7.1=py38_0 - python=3.8.2=hf48f09d_13 - python-dateutil=2.8.1=py_0 - pytorch=1.5.0=py3.8_0 - pytz=2020.1=py_0 - readline=8.0=h1de35cc_0 - requests=2.23.0=py38_0 - scipy=1.4.1=py38h44e99c9_0 - setuptools=46.2.0=py38_0 - six=1.14.0=py38_0 - sqlite=3.31.1=h5c1f38d_1 - tk=8.6.8=ha441bb4_0 - torchvision=0.6.0=py38_cpu - tornado=6.0.4=py38h1de35cc_1 - urllib3=1.25.8=py38_0 - wheel=0.34.2=py38_0 - xz=5.2.5=h1de35cc_0 - zlib=1.2.11=h1de35cc_3 - zstd=1.3.7=h5bba6e5_0 - pip: - dlib==19.19.0 prefix: /path/to/your/anaconda3/envs/pulse 直接使用 pulse.yml 文件,用 Anaconda 进行环境配置。 修改 pulse.yml 文件中 prefix 的路径为你的 Anaconda 路径,然后使用指令创建环境: conda create -f pulse.yml 这是官方推荐的方法。亲测,依然遇到了一些依赖问题。 最后一个一个依赖包安装才解决,所以我建议是使用 Anaconda 通过第三方库的包名安装,不用管版本啥的,例如: conda install ca-certificates requests libcxx、libedit 等这类的 lib 库不用安装,Anaconda 在创建 Python 环境的时候已经安装好了。 这里面稍微难安装的就是 dlib,dlib 需要使用 cmake 进行编译,所以需要先安装好 cmake,这里使用 pip 安装即可: python -m pip install cmake dlib 都搞定了,环境就算搭建完成了。 四、效果测试PULSE 项目地址:https://github.com/adamian98/pulse 下载项目到本地:python git clone https://github.com/adamian98/pulse项目提供了 pretrained model ,模型放在了 Google Drive ,不能翻墙的无法下载。 所以我将模型下载好,上传到了我的百度网盘。 下载地址(提取码:3gpq): https://pan.baidu.com/s/13NZ8RY8KSogY78xh3gpcJA 在工程目录,创建 cache、realpics 两个文件夹,将下载好的三个文件放到 cache 文件夹内。 然后将下图放到 realpics 文件夹内,我们以此图为例,进行测试。图片下载地址:https://cuijiahua.com/wp-content/uploads/2020/07/dl-21-6.jpg 首先,我们使用 align_face.py 对图片 downscale。python align_face.py程序使用 dlib 检测人脸框,并对检测到的人脸进行降低分辨率处理,默认降低为 32x32 分辨率的图片。生成的图片会放到 input 文件夹内,如果将图片放大到 1024x1024,就是相当于一张布满马赛克的图片。有了这张 LR 图片,也就是低分辨率图片,使用 PULSE 算法,看下「脑补」效果吧!python run.py -steps=2000运行 run.py ,迭代 2000 steps,在 runs 文件夹下就会生成“去除”马赛克后的「脑补」图。「脑补」图跟原图还是有些神似的! 五、争议我们都知道,今年 5 月 25 日美国的「跪杀黑人」事件。由此引发了美国有史以来,最大规模的游行抗议。6 月份,吃“美国瓜”的人应该不在少数,比如我就在 YouTube 上吃了一个月的瓜。 每个国家都有自己的敏感话题。 而美国,现在的敏感话题就是「种族歧视」。 PULSE 算法惹了大麻烦。 PULSE 采用 CelebA-HQ 训练的模型,数据集都是白人,因此算法「脑补」出的也都是白人脸。 这在如今高喊「黑命贵」的美国,无疑是一股扎眼的“逆流”。 有网友就拿奥巴马的低分辨率照片进行测试,结果生成的都是白人男性,更加坐实了 PULSE 算法的「种族歧视」罪名。PULSE 算法,以及相关的研究人员,因此被打上了「种族偏见」的标签。 甚至深度学习领军人物 LeCun 因为替 PULSE 说话,也不幸躺枪。 我倒是在想,以后美国科研的数据集是不是也得像美国电影一样,一部剧必须得有黑人演员才行,否则就算「政治不正确」。 扛着「政治正确」大旗的人们“口诛笔伐”异己,欲加之罪,何患无辞。 技术,有罪吗?六、最后PULSE 算法对于非数据集的数据,「脑补」效果一般。想用 PULSE 算法,“去除”人脸以外的马赛克图,需要建立数据集,重新训练模型。 本文原创作者:https://cuijiahua.com/blog/2020/07/dl-21.html

0

深度学习

人脸识别

数据分析

Lucars·2020-07-03 17:32 1 阅读 45
文章使用TensorFlow进行实时目标检测的 API
这是一个基于迁移学习的目标检测API,可检测图像、视频或实时网络摄像头中的所有目标。SSD模型和Faster R-CNN模型连同Tensorflow中的标签图一起在Mobile Net COCO数据集上进行了预训练。这些模型用于检测图像、视频或实时网络摄像头中捕获的目标。OpenCV用于流目标和预处理。 Github​项目地址https://github.com/kaushikjadhav01/Real-Time-Object-Detection-API-using-TensorFlow 一些测试截图使用SSD模型进行图像目标检测的输出结果使用SSD模型进行网络摄像头目标检测的输出结果使用Faster R-CNN模型进行图像目标检测的输出结果使用Faster R-CNN模型进行视频目标检测的输出结果使用Faster R-CNN模型进行网络摄像头目标检测的输出结果技术概念Faster RCNN:是由Ross Girshick, Shaoqing Ren, Kaiming He和 Jian Sun 在2015年提出的目标检测架构,并且是使用卷积神经网络(如YOLO(You Look Only Once,仅看一次)和SSD(Single Shot Detector,单帧检测器))的著名目标检测架构之一。更多信息可以查看:https://towardsdatascience.com/faster-rcnn-object-detection-f865e5ed7fc4Single Shot Detector(SSD):像YOLO一样,仅需使用一张照片即可使用多框检测图像中存在的多个物体。它在速度和高精度目标检测算法方面明显更快。更多信息可以查看:https://towardsdatascience.com/ssd-single-shot-detector-for-object-detection-using-multibox-1818603644ca标签映射:是一种将文本与映射符号合理放置在映射上的技术,共同代表现实世界的特征和属性。有效地使用文字可以创建清晰、信息丰富且有吸引力的映射。TensorFlow需要标签映射,即将每个使用的标签映射为整数值。训练和检测过程都使用此映射图。更多信息可以查看:https://tensorflow-object-detection-api-tutorial.readthedocs.io/en/latest/training.html推理图:推理图是一个命题图,其中某些弧和某些反弧都增加了信息可以通过其流动的通道,这意味着推理图既是知识的表示,又是对知识进行推论的方法。Channels 有两种形式。第一种类型,即 i-channels,被添加到反向先行弧中,之所以这样命名,是因为它们承载的消息报告从先前节点到规则节点的“我是真实的”或“我被否定”。Channels 也可以被添加到随后的弧中,称为 u-channels,因为它们将消息传递给结果,从而报告“您是真实的”或“您被否定的”。规则通过共享子表达式连接。更多信息可以查看:http://www.cogsys.org/papers/2013poster15.pdf协议缓冲区(Protobuf):是一种序列化结构化数据的方法。在开发程序之间通过导线相互通信或存储数据时非常有用。该方法涉及描述某些数据结构的界面描述语言和从该描述生成源代码的程序,该程序用于生成或解析表示结构化数据的字节流。更多信息可以查看:http://www.cogsys.org/papers/2013poster15.pdf使用的技术TensorFlow KerasOpenCVIPWebcamPython如何安装使用1.按照说明安装TensorFlow API :https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/installation.md2.下载我的仓库并将仓库的jupyter notebook文件放在 Tensorflow API 的 models/research/object_detection 文件夹中3.如果要使用智能手机摄像头代替笔记本电脑网络摄像头,请从应用程序商店上安装IPWebcam应用程序。打开应用程序,然后点击Start Server4.将我的jupyter笔记本中的IP地址替换为智能手机上IPWebcam应用程序中显示的IP地址,然后运行jupyter notebook项目作者Kaushik JadhavGithub:https://github.com/kaushikjadhav01Medium:https://medium.com/@kaushikjadhav01LinkedIn:https://www.linkedin.com/in/kaushikjadhav01/Portfolio:http://kaushikjadhav01.github.io/

0

深度学习

目标检测

Lucars·2020-07-03 11:42 0 阅读 34
文章顾客照片的自动曝光校正
Automatic Exposure Correction of Consumer PhotographsMethod•本文提出了一种自动曝光校正方法,该方法可以估计给定图像的最佳特定于图像的非线性色调曲线(在本例中为S曲线),自动校正成功的关键是知道每个图像区域的最佳曝光量。 •我们借用摄影中的“zone”概念。区域系统将整个曝光范围量化为11个离散区域。我们将曝光校正定义为区域估计问题,通过同时考虑两个目标来优化全局目标函数来估计每个图像区域中的期望区域:最大化每个区域中的局部细节,以及保持区域之间的相对对比度。 •在得到每个区域的估计区域后,我们提出了一种新的基于非线性曲线的校正算法,称为保细节S曲线调整,以尽可能地将每个区域调整到应该在的zone。与一般的S曲线调整相比,我们的保细节S曲线调整可以保持局部细节,避免光晕效应。General backgroundArchitecture图像进行处理时都会进行归一化处理,在亮度层面进行操作。算法首先会对输入图像进行一些亮度变化,例如直方图均值化,自动色调调整等;然后计算S型曲线未知的两个参数,进而自动校正图像曝光,使得高光和阴影都向图像中间调靠拢,这一步包括区域分割、区域合并、计算可视化细节、区域直方图最短距离和寻找每个区域最优映射区域,最后矫正图像曝光;由于校正后的图像会丢失部分图像细节和色彩,因此最后会对图像进行细节和颜色补偿。Image Segmentation•不像其它图像曝光矫正方法在校正曝光时会对图像整体亮度产生影响,为了对图像不同曝光区域进行不同的曝光矫正处理,需要分割图像,这也是本文求解S型曲线参数的关键。本文采用基于图的图像分割算法,将分割后的图像分解成不同的小区域,将计算的每个区域的像素强度均值作为该区域的曝光值。同时为了更好的区分高光和阴影,作者引进了zone值的概念,zone值范围从0到10共11个分段,其中小于5的为阴影,大于5的为高光,zone值V=5表示中间调,曝光值和zone值的关系,如下图所示:•实现:将计算的亮度均值映射到曝光值,可以设定一个范围,例如以0.1为间隔进行映射。•合并小区域,重新分配zone值。为了更好的矫正具有相同zone值的区域,需要合并这些区域,即合并zone值相同并且相邻的区域,这里需要注意可能存在需要合并的两个区域中间隔着一个区域,而这个区域也与他们zone值相同。合并区域后,重新给合并后的区域分配zone值,上图中的(c)就表示合并后的新区域。 •实现:本次实现时将区域合问题并转换到图像处理问题,因为已经获取了各个区域的坐标,所以将每个区域分别转换为二值图,寻找二值图边界;对区域边界每个像素外扩5*5=25邻域外接16个像素,计算16个像素坐标中是否存在一个落入其它区域,如果是,则这两个区域相邻,同时如果区域值相同,则合并这两个区域。对合并后区域从新分配zone值,获取合并后区域的坐标和区域边缘坐标。•计算任意相邻区域间直方图最短距离。为了曝光矫正后的图像能更好保留原图的对比度,同时为了在求解S型参数时求解最优相邻区域,需要计算不同区域之间的直方图最短距离。该距离定义为两个直方图重叠面积最大时的平移距离,注意该距离需要除以255归一化到[0,1]。如下图所示:•实现:分别计算两个区域图像直方图,一个区域直方图不动,另外一个区域直方图分别从-255到255依次移动,同时计算两个直方图最大重合面积,将最小移动距离作为最终值。•计算每个区域的可恢复细节度值。为了曝光矫正后的图像能更好的保留原图细节,需要计算每个分割区域中可恢复细节程度值。核心原理是使用gamma曲线对图像进行曝光处理,根据不同曝光图像获取的边缘图像计算恢复程度值。 •主要原理是,针对阴影区域,当gamma比较大/比较小时,gamma变换后的图像阴影区域与变换前图像阴影区域差别比较小/比较大,这种区域之间的差别可以度量最终矫正曝光时图像细节的恢复程度。高光区域同理。计算细节程度主要依据每个区域边缘像素数占图像所有边缘像素数的比值确定,具体计算过程如下:•计算最优区域。获取了直方图间最短距离和可恢复图像细节程度,就可以根据它们计算每个区域需要映射的像素强度值,该强度值是在所有区域中寻找与该区域期望值最小的那个区域作为目标映射对象。进一步而言是p(i)和p(i,j)最大的两个区域对为最优区域组合,再细一点就是两个区域在细节程度和直方图距离最接近为最优,这样能保证曝光矫正不是很突兀,尽可能在亮度之间平滑过渡。优化等式如下:其中:Experiment

1

机器学习

JASPER_W_·2020-06-30 10:26 3 阅读 61
文章基于提升决策树算法预测镁合金屈服强度
摘要可生物降解的镁合金植入材料可以实现永久性植入体的临床功能,并且在完成其支撑上的功能而对组织修复不再有用时,装置可在人体环境中降解。作为一种新型植入材料研究,目前镁合金材料的力学性能与腐蚀速率往往不能兼顾,支撑强度不够是其发展的一项阻碍。机器学习旨在从数据库中提取信息并获得分析能力,根据以往的数据计算训练,以产生可靠、可重复的决策和结果,在分类、回归和与高维数据相关的其他任务中表现出良好的适用性。机器学习在许多领域发挥了重要作用,现已被用于解决材料科学中的各种问题,例如新材料发现和材料特性预测。本文从目前已发表的镁合金的研究数据出发,应用机器学习算法主要针对镁合金材料的合金元素、热处理对其力学性能的影响进行分析和模型组建,并得出一个可以泛化的预测模型。金属材料作为生物医用材料一直以来发挥着重要的作用,目前已经研究了很多金属材料用于辅助修复或替换已经患病或受损的骨组织。相比于陶瓷或聚合物材料,金属因为具有高机械强度和断裂韧性而适合于承载应用,目前常用的金属生物材料包括不锈钢、Ti和Co-Cr基合金。金属材料在长期植入后可能通过腐蚀或磨损过程释放有毒金属离子、诱发炎症同时破坏材料的生物相容性并导致组织损伤,实际上金属材料存在这样的问题因此在使用中受到颇多局限。GBDT(Gradient Boosting Decision Tree) 也可以称之为MART(Multiple Additive Regression Tree),是一种迭代的决策树算法,该算法由多棵决策树组成,在回归问题的处理上采用CART决策树进行。该方法背后的基本原理是:许多简单学习器的预测加权平均值可能优于复杂的学习器。其中所谓的Boosting是指构建全局预测模型的一般方案。每一个独立的决策树可能是弱的预测器,提升算法基于在训练数据的变化模型上生成大量的简单模型(即弱的预测器),并将所有树输出的加权和作为最终预测结果,那么这个集成的模型会产生更好的预测。它在被提出之初就和SVM一起被认为是泛化能力较强的算法。需要声明的一点是GBDT中的树完全是回归树,用来做回归预测。使用回归树和平方误差损失函数的提升算法的主要步骤可归纳如下:i.首先用开始的目标平均值作为预测: ii.对于m=1到M的多个树:a)计算在训练集中的预测误差: b)从训练集中抽取一个随机子样本Smc)考虑Sm重新建立回归树并拟合到前一个集合的残差中: d)更新整体决策树,将上一树的预测值与第m颗树产生的残差相加作为整体决策树的预测值: iii.最后将作为最终的提升预测值,通常在这个过程中认为这个过程容易因为训练误差随着每次迭代而减少,产生过度拟合的情况,为了克服这个问题,添加正则化参数以进行改进。 目前总计采用研究文章50篇中的实验数据进行计算分析,其中包括中文研究文章21篇(其中包括4篇硕、博士论文),外文研究文章29篇,包含发表时间在2000-2018年间的文章。收集有镁合金数据215组,所谓“组”是指包括材料的合金元素成分、处理工艺(包括处理温度、时间)、以及材料的屈服强度(Yield Strength)的一个数据集。本研究采集到的每组数据在成份、加工、热处理上都有着明确的差异。在调查近十年关于镁合金的研究、收集了大量的铸造态镁合金的合金添加数据、热处理数据以及相应的合金屈服强度数据后,通过Microsoft Azure ML Studio机器学习实验室的算法,包括:线性回归、贝叶斯回归、神经网络回归、以及提升决策树算法回归分别建立了对应与数据集的训练模型。其中提升决策树算法模型的决定系数最高R2=0.8088,训练误差集中在0-35之间,是为相对适合该数据集的算法。针对该模型进行大量参数组合的覆盖式调参训练,共计9862次,最终得出最优的参数组合,在该参数下,模型的决定系数提高到R2=0.8930,提高决定系数的同时降低了模型的各项训练误差。在此基础上建立了预测模型以及用户交互界面,可以通过终端输入相关参数对未知镁合金的屈服强度进行初步的预测。最终对一则并未出现在数据集中的镁合金数据应用该预测模型,以预测其屈服强度并与实验数据进行了对比,预测结果较为接近且误差普遍在10以内。另外,受限与数据集的规模较小,该模型的泛化能力有限,未来在吸纳更多的镁合金相关数据后,可以对模型进行改进并得出更逼近实验值的预测数据。

1

机器学习

会员1593326284·2020-06-29 11:29 0 阅读 54
文章关于非极大抑制NMS
在物体检测中NMS(Non-maximum suppression)非极大抑制应用十分广泛,其目的是为了消除多余的框,找到最佳的物体检测的位置。 在RCNN系列算法中,会从一张图片中找出很多个候选框(可能包含物体的矩形边框),然后为每个矩形框为做类别分类概率。就像上面的图片一样,定位一个车辆,最后算法就找出了一堆的方框,我们需要判别哪些矩形框是没用的。   非极大值抑制:先假设有6个候选框,根据分类器类别分类概率做排序,从小到大分别属于车辆的概率分别为:A、B、C、D、E、F。1、从最大概率矩形框F开始,分别判断A~E与F的重叠度IOU是否大于某个设定的阈值;   2、假设B、D与F的重叠度超过阈值,那么就扔掉B、D;并标记第一个矩形框F,是我们保留下来的。   3、从剩下的矩形框A、C、E中,选择概率最大的E,然后判断E与A、C的重叠度,重叠度大于一定的阈值,那么就扔掉;并标记E是我们保留下来的第二个矩形框。4、一直重复这个过程,找到所有曾经被保留下来的矩形框。  非极大值抑制(NMS)非极大值抑制顾名思义就是抑制不是极大值的元素,搜索局部的极大值。例如在对象检测中,滑动窗口经提取特征,经分类器分类识别后,每个窗口都会得到一个分类及分数。但是滑动窗口会导致很多窗口与其他窗口存在包含或者大部分交叉的情况。这时就需要用到NMS来选取那些邻域里分数最高(是某类对象的概率最大),并且抑制那些分数低的窗口。

1

目标检测

PJiii·2020-06-29 11:25 0 阅读 59
文章如何对模型进行优化
前言:先是给出pytorch的训练模型,验证模型,以数据进行划分,如何调学习率,什么是TTA,给出相应的方案,并简述一下我的调参经验pytorch中的训练模型def train(train_loader, model, criterion, optimizer, epoch): # 切换模型为训练模式 model.train() train_loss = [] for i, (input, target) in enumerate(tqdm(train_loader)): if use_cuda: input = input.cuda() target = target.cuda() print("cuda is ok") c0, c1, c2, c3, c4 = model(input) else: print("cuda is not done") target = target.long() loss = criterion(c0, target[:, 0]) + \ criterion(c1, target[:, 1]) + \ criterion(c2, target[:, 2]) + \ criterion(c3, target[:, 3]) + \ criterion(c4, target[:, 4]) # loss /= 6 optimizer.zero_grad() loss.backward() optimizer.step() train_loss.append(loss.item()) return np.mean(train_loss) pytorch中的验证模型def validate(val_loader, model, criterion): # 切换模型为预测模型 model.eval() val_loss = [] # 不记录模型梯度信息 with torch.no_grad(): for i, (input, target) in enumerate(tqdm(val_loader)): if use_cuda: input = input.cuda() target = target.cuda() c0, c1, c2, c3, c4 = model(input) target = target.long() loss = criterion(c0, target[:, 0]) + \ criterion(c1, target[:, 1]) + \ criterion(c2, target[:, 2]) + \ criterion(c3, target[:, 3]) + \ criterion(c4, target[:, 4]) # loss /= 6 val_loss.append(loss.item()) return np.mean(val_loss) 这里我在经过了非常久的训练后发现,在训练完后中断后,再次训练没有’调用’这个之前训练完的参数会从头开始训练,对于网络的优化的时间又要更久一些,因此我在这里就调用我之前训练后保存的模型,来减少悬链的这里我为了保存模型和调用学到的模型,在 model = SVHN_Model1() state_dict=torch.load('bsbest.pt') model.load_state_dict(state_dict) 在实例化模型之后调用之前学过,训练的时间就减少了 我的调差 首先,最为简单的就是调大batch_size,调到gpu能够选到的范围*对于学习率,一般来说先是进行,基于自己的情况,能够有足够的训练次数时,先是学习率的步长大一些观察训练的损失情况,然后在可以选择对学习率的调整,然后在后面学习率调小一些,具体可以参考这篇博客还有就是用“cosine” decay,比较有用效果对于网络结构的有化,运用relu,dropout的方法在网络结构上 这个在yolov4中作者也用到了这个调学习率的方法,是yolov4能够在yolov3的基础上还能够提升的一个原因 参考论文 数据集的划分 深度学习离不开数据,好的数据往往能够让我们的效率事半功倍,最为常见的数据划分的方法就是划分9:1的训练集和验证集,除此之外还可以划分如下图所示*的交叉验证,在每个数据集上留出一部分作为验证集可以参考这篇博客 进行正则化学习过深度学习,机器学习都会知道什么是正则化,无非最为常见的的包括L1正则化和L2正则化,先给出数学公式:L1的表达式为:L2的表达式为:λ∈(0,1)在pytorch可用SGD来实现随机梯度下降 optimizer = optim.SGD(model.parameters(), lr = 0.01, momentum=0.9,weight_decay=1e-5) 其中SGD为随机梯度下降的算法,weight_decay为权重衰减值(这里说句题外话,pytorch等框架的好处就是不用自己写公式就可实现对一些复杂公式的实现,只需要调用API就能够轻松的实现,想这个梯度下降直接调用就可以了,还有就是像反向传播不用自己写就只要在pytorch写好前向传播就可以实现了,真的是时代在变化,可能在过不久就可以普遍实现前端输入参数就可以进行训练了)各种pytorch的正则化可以参考这篇博客 加入Dropout 相信入门深度学习的人都听说过来段英文的解释Deep neural nets with a large number of parameters are very powerful machine learning systems. However, overfitting is a serious problem in such networks. Large networks are also slow to use, making it difficult to deal with overfitting by combining the predictions of many different large neural nets at test time. Dropout is a technique for addressing this problem. The key idea is to randomly drop units (along with their connections) from the neural network during training. This prevents units from co-adapting too much. During training, dropout samples from an exponential number of different “thinned” networks. At test time, it is easy to approximate the effect of averaging the predictions of all these thinned networks by simply using a single unthinned network that has smaller weights. This significantly reduces overfitting and gives major improvements over other regularization methods. We show that dropout improves the performance of neural networks on supervised learning tasks in vision, speech recognition, document classification and computational biology, obtaining state-of-the-art results on many benchmark data sets.==带有大量参数的深度神经网络是非常强大的机器学习系统。然而,在这样的网络中,过度拟合是一个严重的问题。大型神经网络的使用也很缓慢,因此很难通过在测试时结合许多不同大型神经网络的预测来处理过拟合问题。dropout是一种解决这个问题的技术。关键的想法是在训练过程中从神经网络中随机丢弃单元(以及它们的连接)。这可以防止单位之间的相互适应过度。在培训期间,辍学指数样本数量的不同thinneda网络。在测试时,只需使用一个权重较小的网络,就可以很容易地估计出所有这些网络的预测的平均效果。这大大减少了过度拟合,并对其他正则化方法进行了重大改进。我们发现,在视觉、语音识别、文档分类和计算生物学等监督学习任务中,dropout提高了神经网络的性能,在许多基准数据集上获得了最先进的结果。== #具体的在pytorch上的用法很简单 class SVHN_Model1(nn.Module): def __init__(self): super(SVHN_Model1, self).__init__() model_conv = models.resnet18(pretrained=True) model_conv.avgpool = nn.AdaptiveAvgPool2d(1) model_conv = nn.Sequential(*list(model_conv.children())[:-1],nn.Dropout(0.25))#这里加dropout self.cnn = model_conv self.fc1 = nn.Linear(512, 11) self.fc2 = nn.Linear(512, 11) self.fc3 = nn.Linear(512, 11) self.fc4 = nn.Linear(512, 11) self.fc5 = nn.Linear(512, 11) 同时运用像是resnet的预训练模型能够让我们在开始的就可能有一个比较好的权重,让训练起来更加的容易,可以通过对数据的特点选择不同的预训练模型 TTA TTA就是测试数据增广的意思,(论文参考)同时在数据增广同时也证明了对于这两篇论文 [1][2]的作用 以下是其中一段论文的翻译“我们采用SPP-net论文[11]中使用的特征图多视图测试策略。在[24,25]中,我们使用稠密滑动窗口方法进一步改进了该策略。首先将卷积层应用到调整大小的全图像上,得到最后的卷积特征图。在feature map中,每个14 14窗口都是使用SPP层[11]合并的。然后将fc层应用于汇集的特征以计算分数。这也是在水平翻转的图像上完成的。将所有稠密滑动窗口的得分取平均值[24,25]。我们进一步在多个尺度上合并这些结果,如[11]” Snapshot 也就是所谓的跳出局部最优解,这个技术对于实验的设备的要求很高

1

深度学习

PyTorch

Feng1583890403·2020-06-23 10:34 0 阅读 182
文章DRCDN:学习深度剩余卷积去雾网络
DRCDN: learning deep residual convolutional dehazing networks简介 文章提出了一种基于卷积神经网络的端到端深度残差卷积去雾网络。其由两个子网组成:一个用于去 雾,另外一个用于优化前者的去雾结果。Motivation文章指出了GFN《Gated Fusion Network for Single Image Dehazing》(门控融合网络)中的几个问 题: GFN从有雾图中得到三个中间结果(白平衡图,对比度增强图,伽马校正图),再通过网络学习这 三个中间结果的权重图。如果这些中间结果不包含足够的信息来去雾,就会产生低质量的去雾结 果。文章直接从模糊图像中提取特征来避免信息损失。 从三个中间结果中学习权重图然后进行混合是一件复杂的任务。文章通过端到端学习避免了复杂的 混合。 以往的方法都是基于室内合成雾数据集来训练的,但是这样的方法不能有效的处理其他户外真实的 图像。文章产生了以下几个想法:  物体以不同比例出现。在过去的某些论文里,使用了多尺度卷积的技巧来提高去雾效果。但是文章 发现这样的做法并不能很好的去雾,所以想到了引入扩张卷积的方式。 但是扩张卷积会引起伪影,残差网络可以消除这样的伪影。Model其中point-wise指1*1的卷积。Dilated指扩张卷积。residual指残差连接。base指基础结果。黄色块和 红色块叠加在一起为最后的去雾结果。虽然文章是和门控融合网络对比,但是网络的本质思路和门控融合网络有本质区别。门控融合网络是先 对有雾图像做基础的增强,然后融合几个增强的结果。而本文和普通的网络一样,只是执行端到端的去 雾映射。损失损失函数为 l1和vgg 损失。对比和测试测试指标PSNR SSIM指标对比结果展示

0

深度学习

JASPER_W_·2020-06-22 16:01 3 阅读 161
文章pytorch实现聊天机器人学习笔记(1)
数据预处理本文以医疗智能问答为例子,简单介绍下seq2seq模型下,pytorch如何实现聊天机器人.由于fly平台提供的竞赛数据都很干净,基本上不需要什么预处理.一般情况下预处理操作也就是把杂乱的问答一一对应起来,形成一个数据集.数据集中每一个问答就是一条记录. 生成词典数据集生成后就需要生成字典.对于中文句子有两种方式生成字典: 1.逐字生成字典,这样生成的字典大小会小一些. 2.分词后,根据分词结果生成字典.此处我一般使用jieba分词. 读取数据集中每条记录,调用以下代码来生成字典 def source2id(self,textline): textline = jieba.lcut(textline) text_list = list() count = len(self.sour2id) for i in range(min(len(textline),128)): if self.sour2id.get(textline[i]): text_list.append(self.sour2id[textline[i]]) else: self.sour2id[textline[i]] = count self.id2sour[count] = textline[i] text_list.append(self.sour2id[textline[i]]) count += 1 text_len = len(text_list) return text_list, text_len 在网上很多文档中会有去掉低频词的操作,但是我个人觉得要视情况而定,不能盲目的去掉低频词.因为有时候关键词反而是低频词语.特别在医疗问答时,很多医疗数据反而是低频的. 为模型准备数据 由于每一个句子长度不一样,所以需要统一把句子padding成max_length(最长句子的长度).这样方便GPU计算.但是同时padding也会带来一个问题.比如,一个句子长度为:4 ,max_length=10,这样实际上后面6个时刻的value都是padding,最终forward的输出应该是第4个时刻的输出,后面的计算都是无用功.所以会生成一个batch_size的列表来记录每个句子的实际长度. 原始的输入通常是batch_size个list,表示batch_size个句子.每次输入的shape大小为(batch_size,max_length).但是seq2seq模型中每个模块用的都是GRU(或者LSTM),而GRU中计算t时刻的输出需要依赖t-1时刻生成的状态值.所以无法在同一个GRU模块中计算一个语句的所有时刻的输出.于是我们需要转换下输入的shape.把(batch_size,max_length)转换成(max_length,batch_size). 上述的两个操作可以通过itertools.zip_longest函数很方便的实现. def zeroPadding(l, fillvalue): return list(itertools.zip_longest(*l, fillvalue=fillvalue)) def get_batches(targets, sources, batch_size, source_padding, target_padding): source_list, source_lens = sources target_list, target_lens = targets for batch_i in range(0, len(source_list)//batch_size): start_i = batch_i * batch_size source_batch = source_list[start_i: start_i + batch_size] source_len_batch = source_lens[start_i: start_i + batch_size] target_batch = target_list[start_i: start_i + batch_size] target_len_batch = target_lens[start_i: start_i + batch_size] max_target_len = max(target_lens[start_i: start_i + batch_size]) pad_sources_batch = zeroPadding(source_batch, source_padding) pad_targets_batch = zeroPadding(target_batch, target_padding) mask= zeroPadding(target_batch, target_padding) yield pad_targets_batch, pad_sources_batch, target_len_batch,max_target_len, source_len_batch,mask 模型的建立1.Encoder Encoder是个RNN,它会遍历输入的每一个Token(词),每个时刻的输入是上一个时刻的隐状态和输入,然后会有一个输出和新的隐状态。这个新的隐状态会作为下一个时刻的输入隐状态。每个时刻都有一个输出,对于seq2seq模型来说,我们通常只保留最后一个时刻的隐状态,认为它编码了整个句子的语义,但是后面我们会用到Attention机制,它还会用到Encoder每个时刻的输出。Encoder处理结束后会把最后一个时刻的隐状态作为Decoder的初始隐状态。 输入: input_seq: 一个batch的输入句子,shape是(max_length, batch_size) input_lengths: 一个长度为batch_size的list,表示句子的实际长度。 hidden: 初始化隐状态(通常是零),shape是(n_layers x num_directions, batch_size, hidden_size) 输出: outputs: 最后一层GRU的输出向量(双向的向量加在了一起),shape(max_length, batch_size, hidden_size) hidden: 最后一个时刻的隐状态,shape是(n_layers x num_directions, batch_size, hidden_size) class EncoderRNN(nn.Module): def __init__(self, hidden_size, embedding,n_layers=1, dropout=0.1): super(EncoderRNN, self).__init__() self.n_layers = n_layers self.hidden_size = hidden_size self.embedding = embedding # 如果只有一层,那么不进行Dropout,否则使用传入的参数dropout进行GRU的Dropout。 self.gru = nn.GRU(hidden_size, hidden_size, n_layers, dropout=(0 if n_layers == 1 else dropout), bidirectional=True) def forward(self, input_seq, input_lengths, hidden=None): # 输入是(max_length, batch),Embedding之后变成(max_length, batch, hidden_size) embedded = self.embedding(input_seq) # Pack padded batch of sequences for RNN module # 因为RNN(GRU)需要知道实际的长度,所以PyTorch提供了一个函数pack_padded_sequence把输入向量和长度pack # 到一个对象PackedSequence里,这样便于使用。 packed = torch.nn.utils.rnn.pack_padded_sequence(embedded, input_lengths,enforce_sorted=False) # 通过GRU进行forward计算,需要传入输入和隐变量 # 如果传入的输入是一个Tensor (max_length, batch, hidden_size) # 那么输出outputs是(max_length, batch, hidden_size*num_directions)。 # 第三维是hidden_size和num_directions的混合,它们实际排列顺序是num_directions在前面,因此我们可以 # 使用outputs.view(seq_len, batch, num_directions, hidden_size)得到4维的向量。 # 其中第三维是方向,第四位是隐状态。 # 而如果输入是PackedSequence对象,那么输出outputs也是一个PackedSequence对象,我们需要用 # 函数pad_packed_sequence把它变成一个shape为(max_length, batch, hidden*num_directions)的向量以及 # 一个list,表示输出的长度,当然这个list和输入的input_lengths完全一样,因此通常我们不需要它。 outputs, hidden = self.gru(packed, hidden) # 参考前面的注释,我们得到outputs为(max_length, batch, hidden*num_directions) outputs, _ = torch.nn.utils.rnn.pad_packed_sequence(outputs) # 我们需要把输出的num_directions双向的向量加起来 # 因为outputs的第三维是先放前向的hidden_size个结果,然后再放后向的hidden_size个结果 # 所以outputs[:, :, :self.hidden_size]得到前向的结果 # outputs[:, :, self.hidden_size:]是后向的结果 # 注意,如果bidirectional是False,则outputs第三维的大小就是hidden_size, # 这时outputs[:, : ,self.hidden_size:]是不存在的,因此也不会加上去。 # 对Python slicing不熟的读者可以看看下面的例子: # >>> a=[1,2,3] # >>> a[:3] # [1, 2, 3] # >>> a[3:] # [] # >>> a[:3]+a[3:] # [1, 2, 3] # 这样就不用写下面的代码了: # if bidirectional: # outputs = outputs[:, :, :self.hidden_size] + outputs[:, : ,self.hidden_size:] outputs = outputs[:, :, :self.hidden_size] + outputs[:, : ,self.hidden_size:] # 返回最终的输出和最后时刻的隐状态。 return outputs, hidden 2.Decoder Decoder也是一个RNN,它每个时刻输出一个词。每个时刻的输入是上一个时刻的隐状态和上一个时刻的输出。一开始的隐状态是Encoder最后时刻的隐状态,输入是特殊的。然后使用RNN计算新的隐状态和输出第一个词,接着用新的隐状态和第一个词计算第二个词,…,直到遇到,结束输出。普通的RNN Decoder的问题是它只依赖与Encoder最后一个时刻的隐状态,虽然理论上这个隐状态(context向量)可以编码输入句子的语义,但是实际会比较困难。因此当输入句子很长的时候,效果会很长。 输入: input_step: shape是(1, batch_size) last_hidden: 上一个时刻的隐状态, shape是(n_layers x num_directions, batch_size, hidden_size) encoder_outputs: encoder的输出, shape是(max_length, batch_size, hidden_size) 输出: output: 当前时刻输出每个词的概率,shape是(batch_size, voc.num_words) hidden: 新的隐状态,shape是(n_layers x num_directions, batch_size, hidden_size) class AttnDecoderRNN(nn.Module): def __init__(self, attn_model, embedding, hidden_size, output_size, n_layers=1, dropout=0.1): super(AttnDecoderRNN, self).__init__() self.attn_model = attn_model self.hidden_size = hidden_size self.output_size = output_size self.n_layers = n_layers self.dropout = dropout # 定义Decoder的layers self.embedding = embedding self.embedding_dropout = nn.Dropout(dropout) self.gru = nn.GRU(hidden_size, hidden_size, n_layers, dropout=(0 if n_layers == 1 else dropout)) self.concat = nn.Linear(hidden_size * 2, hidden_size) self.out = nn.Linear(hidden_size, output_size) self.attn = Attn(attn_model, hidden_size) def forward(self, input_step, last_hidden, encoder_outputs): # 注意:decoder每一步只能处理一个时刻的数据,因为t时刻计算完了才能计算t+1时刻。 # input_step的shape是(1, 64),64是batch,1是当前输入的词ID(来自上一个时刻的输出) # 通过embedding层变成(1, 64, 500),然后进行dropout,shape不变。 embedded = self.embedding(input_step) embedded = self.embedding_dropout(embedded) # 把embedded传入GRU进行forward计算 # 得到rnn_output的shape是(1, 64, 500) # hidden是(2, 64, 500),因为是双向的GRU,所以第一维是2。 rnn_output, hidden = self.gru(embedded, last_hidden) # 计算注意力权重, 根据前面的分析,attn_weights的shape是(64, 1, 10) attn_weights = self.attn(rnn_output, encoder_outputs) # encoder_outputs是(10, 64, 500) # encoder_outputs.transpose(0, 1)后的shape是(64, 10, 500) # attn_weights.bmm后是(64, 1, 500) # bmm是批量的矩阵乘法,第一维是batch,我们可以把attn_weights看成64个(1,10)的矩阵 # 把encoder_outputs.transpose(0, 1)看成64个(10, 500)的矩阵 # 那么bmm就是64个(1, 10)矩阵 x (10, 500)矩阵,最终得到(64, 1, 500) context = attn_weights.bmm(encoder_outputs.transpose(0, 1)) # 把context向量和GRU的输出拼接起来 # rnn_output从(1, 64, 500)变成(64, 500) rnn_output = rnn_output.squeeze(0) # context从(64, 1, 500)变成(64, 500) context = context.squeeze(1) # 拼接得到(64, 1000) concat_input = torch.cat((rnn_output, context), 1) # self.concat是一个矩阵(1000, 500), # self.concat(concat_input)的输出是(64, 500) # 然后用tanh把输出返回变成(-1,1),concat_output的shape是(64, 500) concat_output = torch.tanh(self.concat(concat_input)) # out是(500, 词典大小=7826) output = self.out(concat_output) # 用softmax变成概率,表示当前时刻输出每个词的概率。 output = F.softmax(output, dim=1) # 返回 output和新的隐状态 return output, hidden

0

PyTorch

乐百事·2020-06-22 11:27 0 阅读 129
文章OpenCV图像处理---图像直方图
图像直方图简介:在介绍图像直方图之前,我们先来回顾一下数学中直方图的含义,还记得初中的时候,我们学习过用来表示样本数据的趋势或者分布的统计图吗?折线图和直方图就是代表之一,我们知道折线图是用来表示数据的行走趋势(简单说就是高高低低的一条折线),直方图是用来表示数据中各个类型的数量的(比如说 ,一堆人民币包含了各种数值的钞票,用直方图来表示,你将会观察到10元的有多少张,20元有多少张)的统计图,那么,图像中的直方图是否也是类似的呢?我们看看一下吧,直方图简单来说就是图像中每个像素值的个数统计,比如说一副灰度图中像素值为0的有多少个,1的多少个……直方图是一种分析图片的手段,当然,图像中比较常见的颜色格式是彩色和灰度的,针对灰度图像直方图,我们可以这样理解,灰度直方图是图像中像素灰度集的一种统计反应。它能够描述图像中灰度的分布情况,直观地展现出图像中灰度所占多少。直方图横轴表示像素的灰度范围(比如说 0~255),纵轴表示的是像素的数量或者密度。1.1 原始图像灰度图:1.2 代码实践 直方图实现一:pyplot提供了类似matlab的绘图框架, import matplolib.pyplot as plt plt.hist hist(图像原始数据,像素的范围) 图像的灰度级是0-255,一共256个。因为该直方图函数需要一维数据,所以需要用到ravel()函数,将多维数组降为一维数组。#coding:utf-8 import cv2 # 导入matplotlib.pyplot包,我们需要用到它的函数 import matplotlib.pyplot as plt # 以灰度模式读入图片 gray_img = cv2.imread("./fig.jpg", cv2.IMREAD_GRAYSCALE) cv2.imshow("gray_img", gray_img) # 调用hist函数绘制直方图 plt.hist(gray_img.ravel(), 256) # 显示直方图 plt.show() cv2.waitKey() cv2.destroyAllWindows()效果展示:直方图解读:从图中我们能够很清晰的观察到,灰度值为50左右的像素有2500多个,其余的在100个左右。分布相对均匀。直方图实现二:openv已经为我们准备好了绘制直方图函数, hist = cv2.calcHist(images, channels, mask, histSize, ranges, accumulate) 参数 images : 原始图像 channels : 指定通道通道编号需要用中括号括起来输入图像是灰度图时,它的值为[0]彩色图像可以使[0],[1],[2]分别对应通道B,G,R。mask : 掩码图像统计整幅图像的直方图,设为None。统计图像某一部分的直方图时,需要掩码图像histSize : BINS的数量ranges : 像素值返回RANGE像素值范围,例如:[0, 255]accumulate : 累计标识默认值为false如果被设置为true,则直方图在开始分配时不会被清零该参数允许从多个对象中计算单个直方图,或者用户实施更新直方图多个直方图的累计结果,用户对一组图像计算直方图#coding:utf-8 # 导入matplotlib.pyplot包,我们需要用到它的函数 import matplotlib.pyplot as plt import cv2 # 以灰度模式读入图片 gray_img = cv2.imread("./fig.jpg", cv2.IMREAD_GRAYSCALE) #调用cv2.calcHist()函数绘制直方图 hist = cv2.calcHist([gray_img], [0], None, [256], [0, 255]) # 用绿色绘制 plt.plot(hist, color="g") plt.show()效果展示:直方图解读:通过直方图可以观察到,与上一种绘制结果差不多,仅仅是表现方式不一样,上面的直方图使用长矩形的方式展现的,下面的直方图更侧重于用数学函数,而且是连续的函数进行表达。直方图的作用:从上面的实例我们可以了解到,其实每一个图像的直方图是不一样的,由此,直方图可以用来进行比较不同的图像,不过直方图用到最多的是,均衡化,何为均衡化,简单地说,使得图像的像素值尽量分布均匀,而不是高低差落较大,这样的好处是,能够更好的观察图像的细节部分,如果想要继续学习更多知识,大家敬请关注!今天的文章分享结束了,图像直方图能够让我们直观的看到像素的分布情况,也可以用在精度不是很高的图像识别问题,希望大家下去学会相关函数的使用,实践方知其所以然。

0

Python3

风雨兼程·2020-06-22 11:21 0 阅读 88
没有更多了