问问酷派大神f1联通刷机包,如果要设置联通3G用那个 图片最下面还有一个WG Dualmode

&p&回答这个问题,需要先了解下AES和RSA的区别,前者属于&b&对称加密&/b&,后者属于&b&非对称加密&/b&。&/p&&p&&br&&/p&&h2&&b&1、对称加密&/b&&/h2&&p&对称加密就是&u&加密和解密使用同一个密钥&/u&。&/p&&p&用数学公示表示就是:&/p&&p&▲加密:Ek(P) = C&/p&&p&▲解密:Dk(C) = P&/p&&p&这里E表示加密算法,D表示解密算法,P表示明文,C表示密文。&/p&&p&是不是看起来有点不太容易理解?看下图:&/p&&figure&&img src=&/v2-d87c1cceab55f63c45b84cc_b.png& data-rawwidth=&589& data-rawheight=&207& class=&origin_image zh-lightbox-thumb& width=&589& data-original=&/v2-d87c1cceab55f63c45b84cc_r.png&&&/figure&&p&看过间谍局的知友们一定知道电台和密码本的功能。潜伏里面孙红雷通过电台收听到一堆数字,然后拿出密码本比对,找到数字对应的汉字,就明白上级传达的指令。而军统的监听台没有密码本,只看到一堆没有意义的数字,这就是对称算法的原理。&/p&&p&&i&&u&&b&AES就属于对称加密&/b&,常见的对称加密方法还有DES、3DES、Blowfish、RC2以及国密的SM4。&/u&&/i&&/p&&p&&br&&/p&&h2&&b&2、非对称加密&/b&&/h2&&p&对称加密快而且方便,但是有个缺点——密钥容易被偷或被破解。非对称加密就可以很好的避免这个问题。&/p&&p&非对称算法&b&把密钥分成两个&/b&,一个自己持有叫&b&私钥&/b&,另一个发给对方,还可以公开,叫&b&公钥&/b&,&u&用公钥加密的数据只能用私钥解开&/u&。&/p&&p&▲加密: E公钥(P) = C&/p&&p&▲解密::D私钥(C) = P&/p&&figure&&img src=&/v2-b14e0cb759c4291bbdfbae_b.png& data-rawwidth=&590& data-rawheight=&191& class=&origin_image zh-lightbox-thumb& width=&590& data-original=&/v2-b14e0cb759c4291bbdfbae_r.png&&&/figure&&p&这下就不用担心密钥被对方窃取或被破解了,私钥由自己保管。&/p&&p&非对称加密算法核心原理其实就是设计一个数学难题,使得用公钥和明文推导密文很容易,但根据公钥、明文和密文推导私钥极其难。&/p&&p&&i&&u&&b&RSA&/b&就属于非对称加密,非对称加密还有Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)以及国家商用密码SM2算法。&/u&&/i&&/p&&p&&br&&/p&&h2&&b&3、AES和RSA&/b&&/h2&&p&AES和RSA都很安全,至少在目前的计算机体系结构下,没有任何有效的攻击方式。量子计算机时代,RSA有一定的破绽,因为利用shro's algorithm,量子计算机穷举计算质因子速度可以提高N个数量级,能够在有限的时间内破解RSA密钥。AES256至少目前并没有什么明显的漏洞。&/p&&p&&b&AES作为对称加密技术,加密速度很快。&/b&现在高端一点的CPU都带有AES-NI指令,可以极快的完成加密和解密。&/p&&blockquote&举例来说,坚果云存储系统采用了intel 的AES-NI加速,在采用AES加密和解密的时候,&br&单核的性能可以超过 1GB Byte/秒,非常非常快,很适合对大量数据进行加解密。 &/blockquote&&p&&i&&b&摘自:&/b&&a href=&///?target=http%3A///s/team/security& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&坚果云团队版 - 办公云盘|文件管理|协同办公|企业网盘|安全备份&i class=&icon-external&&&/i&&/a&&/i&&/p&&p&&br&&/p&&p&但是AES作为对称加密技术,如何安全的分发密钥是一个难题。通过任何方式传递密钥都有泄密的风险。当然,目前我国高大上的量子通信技术或许能很好的解决这个问题。&/p&&p&&b&RSA作为非对称加密技术的代表,&/b&加解密的速度其实相当慢,只能对小块的数据进行加解密。但是其非对称的特点,满足公钥可以随处分发,只有公钥能解密私钥加密的数据,只有私钥能解密公钥加密的数据。所以很适合用来进行密钥分发和身份验证,这两个应用场景刚好相反。&/p&&p&1)用于对称秘钥分发的场景,其他人用公钥加密对称的秘钥,那么只有授权人才持有私钥,因此才能解密获得对应的秘钥,解决了AES密钥分发的难题;&/p&&p&2)对于身份验证的场景,授权人用私钥加密一段指令,其他人用公钥解密对应的数据,验证对应的指令与之前约定的某些特征一致(例如,这段话必须使用四川口音,像是坚果云CEO &a class=&member_mention& href=&///people/21f55fcf7b9aace2b6fc46fe& data-hash=&21f55fcf7b9aace2b6fc46fe& data-hovercard=&p$b$21f55fcf7b9aace2b6fc46fe&&@韩竹&/a& 的标准四川口音==),如果一致,那么可以确认这个指令就是授权人发出的。&/p&&p&&br&&/p&&p&&b&相关趣闻轶事:&/b&&/p&&blockquote&RSA除了是一个伟大的发明,被免费开放给所有互联网用户使用。它的发明者还以此成立了一家名为&a href=&///?target=https%3A//en.wikipedia.org/wiki/RSA_Security& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&RSA Security&i class=&icon-external&&&/i&&/a&的网络安全公司,这家公司最后被EMC高价收购。这是德艺双馨的伟大证明, 是“又红又专”的典范。&br&RSA的算法是以三个发明者的名字命名的,三位都是成功的数学家,科学家和企业家,其中的排名第一Ron Rivest,有非常多的杰出贡献。&/blockquote&&p&RSA是整个互联网数据安全的基础,与光纤处于同样基础和重要的方式。&b&大部分的加密和解密的应用都是同时应用RSA和AES。&/b&&/p&&p&&br&&/p&&h2&&b&总结&/b&&/h2&&ol&&li&破解加密的难度除了跟&b&加密方法&/b&有关,还跟&b&密钥长度&/b&以及&b&加密模式&/b&有很大的关系,就拿AES来说,有AES128和AES256(&b&代表密钥长度&/b&),显然AES256的安全性能比AES128更高,而AES又要四种模式:ECB、CBC、CFB、OFB(&b&代表加密模式&/b&)。&/li&&li&RSA1024是属于非对称加密,是基于大整数因式分解难度,也就是两个质数相乘很容易,但是找一个大数的质因子非常困难。量子计算机时代,RSA有一定的风险,具体可以参考:&a href=&///?target=https%3A//en.wikipedia.org/wiki/Shor%2527s_algorithm& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&超链接&i class=&icon-external&&&/i&&/a&&/li&&li&AES256目前没有明显的漏洞,唯一的问题就是如何安全的分发密钥。&/li&&li&现在大部分的加密解密都是同时应用RSA和AES,发挥各自的优势,使用RSA进行密钥分发、协商,使用AES进行业务数据的加解密。&/li&&/ol&
回答这个问题,需要先了解下AES和RSA的区别,前者属于对称加密,后者属于非对称加密。 1、对称加密对称加密就是加密和解密使用同一个密钥。用数学公示表示就是:▲加密:Ek(P) = C▲解密:Dk(C) = P这里E表示加密算法,D表示解密算法,P表示明文,C表示密…
&img src=&/50/v2-5c670aeafdbd43e8710cba24c0407b7e_b.jpg& data-rawwidth=&1920& data-rawheight=&1080& class=&origin_image zh-lightbox-thumb& width=&1920& data-original=&/50/v2-5c670aeafdbd43e8710cba24c0407b7e_r.jpg&&&p&“邮件门”估计是希拉里这辈子栽的最大坑,同时也给网络上的每个人敲响警钟:&b&如何保护隐私数据安全?&/b&&/p&&p&本文的目标读者是那些在乎隐私安全又不具备网络安全知识的用户,不扯理论,直接给解决方案,下载安装后你就可以立即开始保护你的隐私安全,在网络上建立自己的“安全空间”&/p&&img src=&/50/v2-5fbaeebabc2a9b089de6d77a_b.jpg& data-rawwidth=&800& data-rawheight=&450& class=&origin_image zh-lightbox-thumb& width=&800& data-original=&/50/v2-5fbaeebabc2a9b089de6d77a_r.jpg&&&br&&p&------------------------------正文分割线------------------------------&/p&&h2&&b&1.即时通信&/b&&/h2&&p&因为一些不可描述的原因,国内的任何一家聊天软件都没有个人隐私可言,如果你想和密友聊些隐私话题,那么选择可信的第三方IM软件是最佳选择。&/p&&p&&b&推荐一:Hoccer &/b&&a href=&/?target=https%3A///& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Hoccer[iOS/Android]&i class=&icon-external&&&/i&&/a&&/p&&p&Hoccer是德国一家公司的加密聊天软件,本身采用了“端对端”的直接加密方式,且完全匿名不需注册,加解密过程都在手机端进行,除了你和你的聊天对象外任何人无法读取信息,比较小众,但是整体的使用体验很不错,并且数据在加密的基础上还受德联邦数据保护法的保护&a href=&/?target=https%3A///legal-notice/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&法规声明&i class=&icon-external&&&/i&&/a&,我放在第一推荐的原因是:目前还不需翻墙。&/p&&p&&b&推荐二:Telegram&/b&&a href=&/?target=https%3A//telegram.org/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Telegram Messenger&i class=&icon-external&&&/i&&/a&&/p&&p&Telegram因为在安全性方面的优势,早已名声在外,所以很早就被墙了。如果你具备一定的翻墙知识,那么我推荐你使用Telegram。&/p&&p&&b&推荐三:Off-the-Record &/b&&/p&&p&OTR[Off-the-Record]不是一个具体的App,而是一种聊天加密协议,目前的安全界共公认最可靠的即时聊天加密方式。要使用这个服务你需要两部分,一是帮你提供中转的Jabber服务商,二是一款支持OTR的XMPP聊天软件。&/p&&p&服务商最靠谱的推荐&a href=&/?target=https%3A//otr.im& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&OTR.im&i class=&icon-external&&&/i&&/a&,因为这是和OTR开发社区有最纯正血脉联系的服务商。&/p&&p&因为是开源协议,软件可推荐的就非常多了,根据我的使用体验,手机端做的比较好的是ChatSecure,里面已内置了&a href=&/?target=http%3A//OTR.im& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&OTR.im&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a&的注册选项,大家可自行搜索下载。&/p&&h2&&b&2.邮件通讯&/b&&/h2&&p&邮件加密最安全的方式目前来说仍然是PGP加密,如果希拉里一直坚持使用PGP来加密自己的邮件内容,可能现在也就没那么多事儿了,但是繁琐的加解密过程对普通人来说略显麻烦,除了高级别机密的内容,一般情况下只要能做到邮件服务商绝对可信,登录有2-Factor验证,那么对普通人来说也足够了。&/p&&p&&b&推荐一:&a href=&/?target=http%3A//riseup.net& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&riseup.net&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a&&/b&&/p&&p&&a href=&/?target=http%3A//riseup.net& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&riseup.net&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a&是一个致力于为politics活跃分子提供服务的独立社区,逃离棱镜项目之一,他们的邮箱服务不记录你的任何IP信息,并且在发信时会自动抹去邮件头中IP信息,可以做到几乎匿名使用。邮箱申请需要人工审核,不过后来通过率已经很高了。&/p&&p&&b&推荐二:ProtonMail&/b&&/p&&p&这个服务商也挺屌,信誉很高,服务器都在瑞士不受他国政府影响,并且如果你和同时使用他们服务的其他用户互发邮件,会自动启用端对端加密,除了你和收件人谁也不能再读取你们的内容。&/p&&p&&b&不论你使用哪个服务商,紧记两点:&/b&&/p&&ul&&li&密码一定要保护好,并且一定要开启两步验证,使用yubikey或Google Authnicator来保护你的账号安全。&br&&/li&&li&发送高级机密信息一定使用PGP机密,在网上关于PGP的教程多如牛毛,就不在这里赘笔了。&br&&/li&&/ul&&br&&h2&&b&3.硬盘数据安全&/b&&/h2&&p&冠希老师如果早了解基本的加密常识,也就不会有后面那么多事儿了,硬盘加密我们主要考虑两点:&/p&&ol&&li&硬盘丢失不担心被别人读取&/li&&li&被人暴力胁迫交出密码,也可以保护高级别隐私内容&/li&&/ol&&p&&b&推荐一:VeraCrypt&/b&&/p&&p&这是在TrueCrypt基础上开发的增强版硬盘加密软件,因为TrueCrypt已经停止更新,所以这是一个很好的替代选择。可以在创建的加密盘内再创建一个隐藏分区,就算被人暴力胁迫交出外盘的密码也可以保护隐藏分区里的内容。&/p&&p&&b&推荐二:DiskCryptor&/b&&/p&&p&这也是逃离棱镜项目之一,功能上没有VeraCrypt强大些,只能整个分区加密或全盘加密,没有创建一个文件加密分区的功能。但是因为名声在外,在这里也像大家推荐。&/p&
“邮件门”估计是希拉里这辈子栽的最大坑,同时也给网络上的每个人敲响警钟:如何保护隐私数据安全?本文的目标读者是那些在乎隐私安全又不具备网络安全知识的用户,不扯理论,直接给解决方案,下载安装后你就可以立即开始保护你的隐私安全,在网络上建立自…
&p&其实客观来讲,在服务端开发中考量更多的并不是什么语法糖能带来多大的开发便捷。语言语法精简完备能为开发带来一定的便捷,但是无论是什么语言,要构建一个完备的分布式系统,语言层次的东西就是其次了的。&/p&&p&比如说,当我在考虑使用分布式进程通信协议的时候,我会优先考虑有什么优秀而完备的RPC库。以基于etcd v3的gRPC为例, 该协议有这么一堆语言实现&/p&&figure&&img data-rawheight=&654& src=&/v2-2dc0cfa0e0f5bf42b1e2_b.png& data-rawwidth=&1422& class=&origin_image zh-lightbox-thumb& width=&1422& data-original=&/v2-2dc0cfa0e0f5bf42b1e2_r.png&&&/figure&&p&那么像 rust,lisp 一类的无实现的语言就在考虑的时候被优先pass掉了。但如果scala或者kotlin这一些语言能做到兼容java库,那么这些语言都应该被归为考虑中。&/p&&p&又比如当需要用到redis集群的时候我会优先想到ruby或者go, 前者有很好的集群api支持,后者有语言级的协程库来实现并发高效。当然jedis最新版本有实现集群api所以java系的也在考虑之中。&/p&&p&如上这一过程作为例子其实是为了表达一个观点: 在决定语言与架构的时候,会根据&概念-&找实现库-&确认实现库的可行性&这个过程进行过滤。而在这个过程中,对语法糖的考量其实是挺少的。(实际开发中JavaScript这种fuck math的语言都能用,还有什么语言语法是不能能被接受的?)&/p&&p&从上面那个角度来看,kotlin是比较幸运的。首先从语言层面上,除了cglib等少数java库需要配置allopen插件才能正常工作以外,大多数java库都是能正常调用的。其次从功能层面上,spring全家桶(很抱歉但我就是喜欢这么叫)包含了服务端开发的大部分功能套件,而spring的最新版本(&a href=&///?target=https%3A//spring.io/blog//introducing-kotlin-support-in-spring-framework-5-0& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Introducing Kotlin support in Spring Framework 5.0&i class=&icon-external&&&/i&&/a&)也注重了和kotlin这门语言的兼容(比如jackson的kotlin插件等)。使用spring全家桶,可以完全参看文档解决所有兼容性问题,目前看来就是这么简单。然后从语法层次上,它提供了不少java里缺少的高级语法特性,一定程度上解决了java备受诟病的啰嗦问题。&/p&&p&最后在回归到问题本身来说,kotlin作为服务端开发是&b&可行的&/b&。相较于java,它提供了更多的一些高级语法特性(非空检测,智能类型判断等),在&b&对语言充分掌握&/b&的情况下一定能降低开发成本和错误率。&/p&&p&这里还是安利一波社区项目,kotlin 社区问答版&a href=&///?target=https%3A//kotlin-cn.org/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Kotlin China&i class=&icon-external&&&/i&&/a&,github地址在&a href=&///?target=https%3A///Kotlin-lang-CN/Kotlin-CN& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Kotlin-lang-CN/Kotlin-CN&i class=&icon-external&&&/i&&/a&。该项目服务使用 kotlin 编写构建,采用etcd+自定义TCP协议的RPC做服务调度的分布式架构,使用了轻量级web框架spark作为controller(本人崇尚精简,并不想用spring全家桶)&/p&&p&我们致力于提供最好的Kotlin中文教程 共建最潮流的Kotlin中文社区&/p&
其实客观来讲,在服务端开发中考量更多的并不是什么语法糖能带来多大的开发便捷。语言语法精简完备能为开发带来一定的便捷,但是无论是什么语言,要构建一个完备的分布式系统,语言层次的东西就是其次了的。比如说,当我在考虑使用分布式进程通信协议的时候…
&h2&导语&/h2&&p&MySQL 作为最受欢迎的开源数据库,也是云上使用最多的数据库,在实际业务中应用广泛。但在实际应用经常遇到 MySQL 各种各样的瓶颈,比如:如何优化 MySQL 、怎么完成数据库迁移、应掌握 MySQL 哪些关键问题以及数据库的性能问题等等。 不少鹅厂工程师针对这些问题在&a href=&/?target=https%3A///community/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&腾讯云技术社区&i class=&icon-external&&&/i&&/a&上分享了 MySQL 实战技术经验,小编在此梳理了一些干货,让我们跟着腾讯工程师一起玩转 MySQL 。&/p&&h2&CDB 内核优化&/h2&&p&由于 MySQL 在实践应用中存在对于事务性支持不太好、多个分支、读写效率瓶颈等问题,所以如何用好MYSQL变得至关重要。在腾讯云,因为用户数的不断增加,对CDB for MySQL提出越来越高的要求,腾讯云CDB团队针对用户的需求和业界发展的技术趋势,对 &a href=&/?target=https%3A///product/cdb& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&CDB for MySQL&i class=&icon-external&&&/i&&/a& 分支进行深度的定制优化。以下三篇技术干货将为大家介绍如何对MySQL进行内核级优化的思路和经验。&/p&&a href=&/?target=https%3A///community/article/011891& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&MySQL 内核深度优化&i class=&icon-external&&&/i&&/a&&a href=&/?target=https%3A///community/article/199519& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&腾讯云 CDB 内核特性与优化实践&i class=&icon-external&&&/i&&/a&&a href=&/?target=https%3A///community/article/348437& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&腾讯云数据库优化最佳实战:以 TXSQL 为例&i class=&icon-external&&&/i&&/a&&h2&MySQL 优化&/h2&&p&学习了 MySQL 内核级优化的思路和经验。那么,当谈到 MySQL 优化时,你会谈些什么呢?以下两篇文章是作者根据自己的实践经验以及曾经踩过的坑,总结出的一些 MySQL 索引原理以及常用的sql查询优化的理解与实践,希望对 MySQL 的开发者有所启发。&/p&&a href=&/?target=https%3A///community/article/382852& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&MySQL 索引及查询优化总结&i class=&icon-external&&&/i&&/a&&a href=&/?target=https%3A///community/article/302356& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&当谈 SQL 优化时谈些什么?&i class=&icon-external&&&/i&&/a&&h2&关键知识点&/h2&&p&MySQL 有关的话题不仅仅是性能优化,还有其高可用性、强一致性、高性能、纵向扩展、负载均衡、读写分离等等。然而要想掌握其中的精髓,可得花费不少功力。以下两位笔者通过研发项目的实践经验分别梳理了 MySQL 的技术点以及 MySQL 比较具有代表性的问题。&/p&&a href=&/?target=https%3A///community/article/011945& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&MySQL 开发实践 8 问,你能 hold 住几个?&i class=&icon-external&&&/i&&/a&&a href=&/?target=https%3A///community/article/214392& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&埋在 MYSQL 数据库应用中的17个关键问题!&i class=&icon-external&&&/i&&/a&&h2&高性能与高可用&/h2&&p&以上提到 MySQL 有关的话题不仅仅是性能优化,还有其高可用性以及高性能。众所周知,MySQL 数据库是目前开源应用最大的关系型数据库,有海量的应用将数据存储在 MySQL 数据库中。存储数据的安全性和可靠性是生产数据库的关注重点。接下来的两篇文章对其性能进行测试与分析并总结经验,以及分析了目前采用较多的保障 MySQL 可用性方案。&/p&&a href=&/?target=https%3A///community/article/328526& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&MySQL 性能测试经验&i class=&icon-external&&&/i&&/a&&a href=&/?target=https%3A///community/article/011915& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&MySQL 数据库的高可用性分析&i class=&icon-external&&&/i&&/a&&h2&MySQL 迁移&/h2&&p&那么,如果因为业务需要,将数据库进行迁移,如何保证业务迁移顺利进行,迁移过程中遇到问题该如何快速解决等等一系列迁移问题。以下两篇文章分享了创梦者和某国内大型游戏开发商数据库搬迁到腾讯云数据库的实际迁移经验,并详细阐述了一些数据库迁移过程的解决思路和小窍门。&/p&&a href=&/?target=https%3A///community/article/011834& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&存储总量达 20T 的 MySQL 实例,如何完成迁移?&i class=&icon-external&&&/i&&/a&&a href=&/?target=https%3A///community/article/682199& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&基于 Discuz 的 Mysql 云数据库搬迁实例解析&i class=&icon-external&&&/i&&/a&&h2&结语&/h2&&p&以上的几篇文章主要介绍了 MySQL 的性能优化、高性能以及高可用等特性,总结了 MySQL 必须掌握的关键技术点,以及阐述了数据库迁移问题。&/p&&p&如果你有一定的技术分享习惯,也想和鹅厂前端、后台技术、安全大牛们深度交流。&/p&&p&那推荐你加入:&a href=&/?target=https%3A///community/article/593405& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&腾讯云社区技术作者扶持计划 - 腾云阁 - 腾讯云&i class=&icon-external&&&/i&&/a&,和大神们同群抢红包...&/p&
导语MySQL 作为最受欢迎的开源数据库,也是云上使用最多的数据库,在实际业务中应用广泛。但在实际应用经常遇到 MySQL 各种各样的瓶颈,比如:如何优化 MySQL 、怎么完成数据库迁移、应掌握 MySQL 哪些关键问题以及数据库的性能问题等等。 不少鹅厂工程师针…
&img src=&/50/v2-da6e908fbff06e8e14c60d86d776d225_b.jpg& data-rawwidth=&768& data-rawheight=&576& class=&origin_image zh-lightbox-thumb& width=&768& data-original=&/50/v2-da6e908fbff06e8e14c60d86d776d225_r.jpg&&&img src=&/v2-abd42bbb61ee_b.jpg& data-rawwidth=&558& data-rawheight=&315& class=&origin_image zh-lightbox-thumb& width=&558& data-original=&/v2-abd42bbb61ee_r.jpg&&&p&作为一名久经片场的老司机,早就想写一些探讨驾驶技术的文章。这篇就介绍利用生成式对抗网络(GAN)的两个基本驾驶技能:&br&&/p&&p&1) 去除(爱情)动作片中的马赛克&/p&&p&2) 给(爱情)动作片中的女孩穿(tuo)衣服&/p&&br&&h2&生成式模型&/h2&&p&上一篇《&a href=&/p/& class=&internal&&用GAN生成二维样本的小例子&/a&》中已经简单介绍了GAN,这篇再简要回顾一下生成式模型,算是补全一个来龙去脉。&/p&&p&生成模型就是能够产生指定分布数据的模型,常见的生成式模型一般都会有一个用于产生样本的简单分布。例如一个均匀分布,根据要生成分布的概率密度函数,进行建模,让均匀分布中的样本经过变换得到指定分布的样本,这就可以算是最简单的生成式模型。比如下面例子:&/p&&img src=&/v2-d11b5fb26d3cc8e942f841bafe010cd8_b.png& data-rawwidth=&1021& data-rawheight=&443& class=&origin_image zh-lightbox-thumb& width=&1021& data-original=&/v2-d11b5fb26d3cc8e942f841bafe010cd8_r.png&&&p&图中左边是一个自定义的概率密度函数,右边是相应的1w个样本的直方图,自定义分布和生成这些样本的代码如下:&br&&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&kn&&from&/span& &span class=&nn&&functools&/span& &span class=&kn&&import&/span& &span class=&n&&partial&/span&
&span class=&kn&&import&/span& &span class=&nn&&numpy&/span&
&span class=&kn&&from&/span& &span class=&nn&&matplotlib&/span& &span class=&kn&&import&/span& &span class=&n&&pyplot&/span&
&span class=&c1&&# Define a PDF&/span&
&span class=&n&&x_samples&/span& &span class=&o&&=&/span& &span class=&n&&numpy&/span&&span class=&o&&.&/span&&span class=&n&&arange&/span&&span class=&p&&(&/span&&span class=&o&&-&/span&&span class=&mi&&3&/span&&span class=&p&&,&/span& &span class=&mf&&3.01&/span&&span class=&p&&,&/span& &span class=&mf&&0.01&/span&&span class=&p&&)&/span&
&span class=&n&&PDF&/span& &span class=&o&&=&/span& &span class=&n&&numpy&/span&&span class=&o&&.&/span&&span class=&n&&empty&/span&&span class=&p&&(&/span&&span class=&n&&x_samples&/span&&span class=&o&&.&/span&&span class=&n&&shape&/span&&span class=&p&&)&/span&
&span class=&n&&PDF&/span&&span class=&p&&[&/span&&span class=&n&&x_samples&/span& &span class=&o&&&&/span& &span class=&mi&&0&/span&&span class=&p&&]&/span& &span class=&o&&=&/span& &span class=&n&&numpy&/span&&span class=&o&&.&/span&&span class=&n&&round&/span&&span class=&p&&(&/span&&span class=&n&&x_samples&/span&&span class=&p&&[&/span&&span class=&n&&x_samples&/span& &span class=&o&&&&/span& &span class=&mi&&0&/span&&span class=&p&&]&/span& &span class=&o&&+&/span& &span class=&mf&&3.5&/span&&span class=&p&&)&/span& &span class=&o&&/&/span& &span class=&mi&&3&/span&
&span class=&n&&PDF&/span&&span class=&p&&[&/span&&span class=&n&&x_samples&/span& &span class=&o&&&=&/span& &span class=&mi&&0&/span&&span class=&p&&]&/span& &span class=&o&&=&/span& &span class=&mf&&0.5&/span& &span class=&o&&*&/span& &span class=&n&&numpy&/span&&span class=&o&&.&/span&&span class=&n&&cos&/span&&span class=&p&&(&/span&&span class=&n&&numpy&/span&&span class=&o&&.&/span&&span class=&n&&pi&/span& &span class=&o&&*&/span& &span class=&n&&x_samples&/span&&span class=&p&&[&/span&&span class=&n&&x_samples&/span& &span class=&o&&&=&/span& &span class=&mi&&0&/span&&span class=&p&&])&/span& &span class=&o&&+&/span& &span class=&mf&&0.5&/span&
&span class=&n&&PDF&/span& &span class=&o&&/=&/span& &span class=&n&&numpy&/span&&span class=&o&&.&/span&&span class=&n&&sum&/span&&span class=&p&&(&/span&&span class=&n&&PDF&/span&&span class=&p&&)&/span&
&span class=&c1&&# Calculate approximated CDF&/span&
&span class=&n&&CDF&/span& &span class=&o&&=&/span& &span class=&n&&numpy&/span&&span class=&o&&.&/span&&span class=&n&&empty&/span&&span class=&p&&(&/span&&span class=&n&&PDF&/span&&span class=&o&&.&/span&&span class=&n&&shape&/span&&span class=&p&&)&/span&
&span class=&n&&cumulated&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&
&span class=&k&&for&/span& &span class=&n&&i&/span& &span class=&ow&&in&/span& &span class=&nb&&range&/span&&span class=&p&&(&/span&&span class=&n&&CDF&/span&&span class=&o&&.&/span&&span class=&n&&shape&/span&&span class=&p&&[&/span&&span class=&mi&&0&/span&&span class=&p&&]):&/span&
&span class=&n&&cumulated&/span& &span class=&o&&+=&/span& &span class=&n&&PDF&/span&&span class=&p&&[&/span&&span class=&n&&i&/span&&span class=&p&&]&/span&
&span class=&n&&CDF&/span&&span class=&p&&[&/span&&span class=&n&&i&/span&&span class=&p&&]&/span& &span class=&o&&=&/span& &span class=&n&&cumulated&/span&
&span class=&c1&&# Generate samples&/span&
&span class=&n&&generate&/span& &span class=&o&&=&/span& &span class=&n&&partial&/span&&span class=&p&&(&/span&&span class=&n&&numpy&/span&&span class=&o&&.&/span&&span class=&n&&interp&/span&&span class=&p&&,&/span& &span class=&n&&xp&/span&&span class=&o&&=&/span&&span class=&n&&CDF&/span&&span class=&p&&,&/span& &span class=&n&&fp&/span&&span class=&o&&=&/span&&span class=&n&&x_samples&/span&&span class=&p&&)&/span&
&span class=&n&&u_rv&/span& &span class=&o&&=&/span& &span class=&n&&numpy&/span&&span class=&o&&.&/span&&span class=&n&&random&/span&&span class=&o&&.&/span&&span class=&n&&random&/span&&span class=&p&&(&/span&&span class=&mi&&10000&/span&&span class=&p&&)&/span&
&span class=&n&&x&/span& &span class=&o&&=&/span& &span class=&n&&generate&/span&&span class=&p&&(&/span&&span class=&n&&u_rv&/span&&span class=&p&&)&/span&
&span class=&c1&&# Visualization&/span&
&span class=&n&&fig&/span&&span class=&p&&,&/span& &span class=&p&&(&/span&&span class=&n&&ax0&/span&&span class=&p&&,&/span& &span class=&n&&ax1&/span&&span class=&p&&)&/span& &span class=&o&&=&/span& &span class=&n&&pyplot&/span&&span class=&o&&.&/span&&span class=&n&&subplots&/span&&span class=&p&&(&/span&&span class=&n&&ncols&/span&&span class=&o&&=&/span&&span class=&mi&&2&/span&&span class=&p&&,&/span& &span class=&n&&figsize&/span&&span class=&o&&=&/span&&span class=&p&&(&/span&&span class=&mi&&9&/span&&span class=&p&&,&/span& &span class=&mi&&4&/span&&span class=&p&&))&/span&
&span class=&n&&ax0&/span&&span class=&o&&.&/span&&span class=&n&&plot&/span&&span class=&p&&(&/span&&span class=&n&&x_samples&/span&&span class=&p&&,&/span& &span class=&n&&PDF&/span&&span class=&p&&)&/span&
&span class=&n&&ax0&/span&&span class=&o&&.&/span&&span class=&n&&axis&/span&&span class=&p&&([&/span&&span class=&o&&-&/span&&span class=&mf&&3.5&/span&&span class=&p&&,&/span& &span class=&mf&&3.5&/span&&span class=&p&&,&/span& &span class=&mi&&0&/span&&span class=&p&&,&/span& &span class=&n&&numpy&/span&&span class=&o&&.&/span&&span class=&n&&max&/span&&span class=&p&&(&/span&&span class=&n&&PDF&/span&&span class=&p&&)&/span&&span class=&o&&*&/span&&span class=&mf&&1.1&/span&&span class=&p&&])&/span&
&span class=&n&&ax1&/span&&span class=&o&&.&/span&&span class=&n&&hist&/span&&span class=&p&&(&/span&&span class=&n&&x&/span&&span class=&p&&,&/span& &span class=&mi&&100&/span&&span class=&p&&)&/span&
&span class=&n&&pyplot&/span&&span class=&o&&.&/span&&span class=&n&&show&/span&&span class=&p&&()&/span&
&/code&&/pre&&/div&&p&对于一些简单的情况,我们会假设已知有模型可以很好的对分布进行建模,缺少的只是合适的参数。这时候很自然只要根据观测到的样本,学习参数让当前观测到的样本下的似然函数最大,这就是最大似然估计(&b&M&/b&aximum &b&L&/b&ikelihood &b&E&/b&stimation):&br&&/p&&img src=&/equation?tex=%5Chat%7B%5Ctheta%7D%3D%5Coperatorname%2A%7Bargmax%7D_%7B%5Ctheta%7D+P%28%5Cbm%7Bx%7D%7C%5Ctheta%29%0A+%3D+%5Coperatorname%2A%7Bargmax%7D_%7B%5Ctheta%7D+%5Cprod_%7Bi%3D1%7D%5E%7Bn%7DP%28x_i%7C%5Ctheta%29+& alt=&\hat{\theta}=\operatorname*{argmax}_{\theta} P(\bm{x}|\theta)
= \operatorname*{argmax}_{\theta} \prod_{i=1}^{n}P(x_i|\theta) & eeimg=&1&&&br&&p&MLE是一个最基本的思路,实践中用得很多的还有KL散度(Kullback–Leibler divergence),假设真实分布是P,采样分布是Q,则KL散度为:&/p&&img src=&/equation?tex=D_%7BKL%7D%28P%7C%7CQ%29%3D%5Csum_%7Bx+%5Cin+%5COmega%7DP%28%7Bx%7D%29%5Clog%5Cfrac%7BP%28x%29%7D%7BQ%28x%29%7D++& alt=&D_{KL}(P||Q)=\sum_{x \in \Omega}P({x})\log\frac{P(x)}{Q(x)}
& eeimg=&1&&&br&&p&从公式也能看出来,KL散度描述的是两个分布的差异程度。换个角度来看,让产生的样本和原始分布接近,也就是要让这俩的差异减小,所以最小化KL散度就等同于MLE。从公式上来看的话,我们考虑把公式具体展开一下:&/p&&br&&img src=&/equation?tex=%5Cbegin%7Balign%7D%0AD_%7BKL%7D%28P%7C%7CQ%29+%26%3D%5Csum_%7Bx+%5Cin+%5COmega%7DP%28%7Bx%7D%29%5Clog%5Cfrac%7BP%28x%29%7D%7BQ%28x%29%7D++++%5C%5C%0A%26+%3D-%5Csum_%7Bx%5Cin%5COmega%7DP%28%7Bx%7D%29%5Clog%7BQ%28x%29%7D+%2B%5Csum_%7Bx%5Cin%5COmega%7DP%28%7Bx%7D%29%5Clog%7BP%28x%29%7D+%5C%5C%0A%26+%3D-%5Csum_%7Bx%5Cin%5COmega%7DP%28%7Bx%7D%29%5Clog%7BQ%28x%29%7D+%2BH%28P%29%0A%5Cend%7Balign%7D& alt=&\begin{align}
D_{KL}(P||Q) &=\sum_{x \in \Omega}P({x})\log\frac{P(x)}{Q(x)}
& =-\sum_{x\in\Omega}P({x})\log{Q(x)} +\sum_{x\in\Omega}P({x})\log{P(x)} \\
& =-\sum_{x\in\Omega}P({x})\log{Q(x)} +H(P)
\end{align}& eeimg=&1&&&br&&p&公式的第二项就是熵,先不管这项,用H(P)表示。接下来考虑一个小trick:从Q中抽样n个样本&img src=&/equation?tex=%7Bx_1%2Cx_2%2C...%2Cx_n%7D& alt=&{x_1,x_2,...,x_n}& eeimg=&1&&,来估算P(x)的经验值(empirical density function):&br&&/p&&img src=&/equation?tex=%5Chat%7BP%7D%28x%29%3D%5Cfrac+1+n+%5Csum_%7Bi%3D1%7D%5En+%5Cdelta%28x_i-x%29& alt=&\hat{P}(x)=\frac 1 n \sum_{i=1}^n \delta(x_i-x)& eeimg=&1&&&br&&p&其中&img src=&/equation?tex=%5Cdelta%28%5Ccdot%29& alt=&\delta(\cdot)& eeimg=&1&&是狄拉克&img src=&/equation?tex=%5Cdelta& alt=&\delta& eeimg=&1&&函数,把这项替换到上面公式的P(x):&/p&&br&&img src=&/equation?tex=%5Cbegin%7Balign%7D%0AD_%7BKL%7D%28P%7C%7CQ%29+%26%3D-%5Csum_%7Bx%5Cin%5COmega%7D%5Cfrac+1+n+%5Csum_%7Bi%3D1%7D%5En+%5Cdelta%28x_i-x%29%5Clog%7BQ%28x%29%7D+%2BH%28P%29+%5C%5C%0A%26+%3D-%5Cfrac+1+n+%5Csum_%7Bi%3D1%7D%5En+%5Csum_%7Bx%5Cin%5COmega%7D++%5Cdelta%28x_i-x%29%5Clog%7BQ%28x%29%7D+%2BH%28P%29%0A%5Cend%7Balign%7D& alt=&\begin{align}
D_{KL}(P||Q) &=-\sum_{x\in\Omega}\frac 1 n \sum_{i=1}^n \delta(x_i-x)\log{Q(x)} +H(P) \\
& =-\frac 1 n \sum_{i=1}^n \sum_{x\in\Omega}
\delta(x_i-x)\log{Q(x)} +H(P)
\end{align}& eeimg=&1&&&br&&p&因为是离散的采样值,所以&img src=&/equation?tex=%5Csum_%7Bx%5Cin%5COmega%7D+%5Cdelta%28x_i-x%29& alt=&\sum_{x\in\Omega} \delta(x_i-x)& eeimg=&1&&中只有&img src=&/equation?tex=x%3Dx_i& alt=&x=x_i& eeimg=&1&&的时候狄拉克&img src=&/equation?tex=%5Cdelta& alt=&\delta& eeimg=&1&&函数才为1,所以考虑&img src=&/equation?tex=x%3Dx_i& alt=&x=x_i& eeimg=&1&&时这项直接化为1:&/p&&br&&img src=&/equation?tex=D_%7BKL%7D%28P%7C%7CQ%29+%3D-%5Cfrac+1+n%5Csum_%7Bi%3D1%7D%5En+%5Clog%7BQ%28x_i%29%7D+%2BH%28P%29& alt=&D_{KL}(P||Q) =-\frac 1 n\sum_{i=1}^n \log{Q(x_i)} +H(P)& eeimg=&1&&&br&&p&第一项正是似然的负对数形式。&/p&&p&说了些公式似乎跑得有点远了,其实要表达还是那个简单的意思:通过减小两个分布的差异可以让一个分布逼近另一个分布。仔细想想,这正是GAN里面adversarial loss的做法。&/p&&p&很多情况下我们面临的是更为复杂的分布,比如&a href=&/p/& class=&internal&&上篇文章&/a&中的例子,又或是实际场景中更复杂的情况,比如生成不同人脸的图像。这时候,作为具有universal approximation性质的神经网络是一个看上去不错的选择[1]:&br&&/p&&img src=&/v2-6fee20494f50baae2c1dc5fc_b.jpg& data-rawwidth=&1561& data-rawheight=&549& class=&origin_image zh-lightbox-thumb& width=&1561& data-original=&/v2-6fee20494f50baae2c1dc5fc_r.jpg&&&p&所以虽然GAN里面同时包含了生成网络和判别网络,但本质来说GAN的目的还是生成模型。从生成式模型的角度,Ian Goodfellow总结过一个和神经网络相关生成式方法的“家谱”[1]:&/p&&img src=&/v2-8c6f1d8ee39dfbb4fcfb2_b.png& data-rawwidth=&771& data-rawheight=&498& class=&origin_image zh-lightbox-thumb& width=&771& data-original=&/v2-8c6f1d8ee39dfbb4fcfb2_r.png&&&p&在这其中,当下最流行的就是GAN和&b&V&/b&ariational &b&A&/b&uto&b&E&/b&ncoder(VAE),两种方法的一个简明示意如下[3]:&/p&&img src=&/v2-380cde71a2f6ece28b4a97_b.png& data-rawwidth=&568& data-rawheight=&274& class=&origin_image zh-lightbox-thumb& width=&568& data-original=&/v2-380cde71a2f6ece28b4a97_r.png&&&p&本篇不打算展开讲什么是VAE,不过通过这个图,和名字中的autoencoder也大概能知道,VAE中生成的loss是基于重建误差的。而只基于重建误差的图像生成,都或多或少会有图像模糊的缺点,因为误差通常都是针对全局。比如基于MSE(Mean Squared Error)的方法用来生成超分辨率图像,容易出现下面的情况[4]:&/p&&br&&p&&img src=&/v2-78f53b142fab51b0c09a1_b.png& data-rawwidth=&892& data-rawheight=&598& class=&origin_image zh-lightbox-thumb& width=&892& data-original=&/v2-78f53b142fab51b0c09a1_r.png&&在这个二维示意中,真实数据分布在一个U形的流形上,而MSE系的方法因为loss的形式往往会得到一个接近平均值所在的位置(蓝色框)。&/p&&p&GAN在这方面则完爆其他方法,因为目标分布在流形上。所以只要大概收敛了,就算生成的图像都看不出是个啥,清晰度常常是有保证的,而这正是去除女优身上马赛克的理想特性!&/p&&br&&h2&马赛克-&清晰画面:超分辨率(Super Resolution)问题&/h2&&p&说了好些铺垫,终于要进入正题了。首先明确,去马赛克其实是个图像超分辨率问题,也就是如何在低分辨率图像基础上得到更高分辨率的图像:&/p&&img src=&/v2-31c84b42ad_b.png& data-rawwidth=&784& data-rawheight=&324& class=&origin_image zh-lightbox-thumb& width=&784& data-original=&/v2-31c84b42ad_r.png&&&p&视频中超分辨率实现的一个套路是通过不同帧的低分辨率画面猜测超分辨率的画面,有兴趣了解这个思想的朋友可以参考我之前的一个答案:&a href=&/question//answer/& class=&internal&&如何通过多帧影像进行超分辨率重构? &/a&&br&&/p&&p&不过基于多帧影像的方法对于女优身上的马赛克并不是很适用,所以这篇要讲的是基于单帧图像的超分辨率方法。&/p&&h2&SRGAN&/h2&&p&说到基于GAN的超分辨率的方法,就不能不提到SRGAN[4]:《Photo-Realistic Single Image &b&S&/b&uper-&b&R&/b&esolution Using a &b&G&/b&enerative &b&A&/b&dversarial
&b&N&/b&etwork》。这个工作的思路是:基于像素的MSE loss往往会得到大体正确,但是高频成分模糊的结果。所以只要重建低频成分的图像内容,然后靠GAN来补全高频的细节内容,就可以了:&/p&&img src=&/v2-128029dfc7c470b07a4a1_b.png& data-rawwidth=&446& data-rawheight=&131& class=&origin_image zh-lightbox-thumb& width=&446& data-original=&/v2-128029dfc7c470b07a4a1_r.png&&这个思路其实和最早基于深度网络的风格迁移的思路很像(有兴趣的读者可以参考我之前文章&a href=&/p/& class=&internal&&瞎谈CNN:通过优化求解输入图像&/a&的最后一部分),其中重建内容的content loss是原始图像和低分辨率图像在VGG网络中的各个ReLU层的激活值的差异:&p&&img src=&/v2-331e02e394cfd04e7114a_b.png& data-rawwidth=&529& data-rawheight=&150& class=&origin_image zh-lightbox-thumb& width=&529& data-original=&/v2-331e02e394cfd04e7114a_r.png&&生成细节adversarial loss就是GAN用来判别是原始图还是生成图的loss:&/p&&img src=&/v2-fa5af2a10fe9a4dadfb04_b.png& data-rawwidth=&394& data-rawheight=&89& class=&content_image& width=&394&&&p&把这两种loss放一起,取个名叫perceptual loss。训练的网络结构如下:&/p&&img src=&/v2-17861edeb4bcfae4e9f369_b.png& data-rawwidth=&780& data-rawheight=&400& class=&origin_image zh-lightbox-thumb& width=&780& data-original=&/v2-17861edeb4bcfae4e9f369_r.png&&&p&正是上篇文章中讲过的C-GAN,条件C就是低分辨率的图片。SRGAN生成的超分辨率图像虽然PSNR等和原图直接比较的传统量化指标并不是最好,但就视觉效果,尤其是细节上,胜过其他方法很多。比如下面是作者对比bicubic插值和基于ResNet特征重建的超分辨率的结果:&/p&&img src=&/v2-f3b4376938ffcbd23c42d_b.png& data-rawwidth=&981& data-rawheight=&392& class=&origin_image zh-lightbox-thumb& width=&981& data-original=&/v2-f3b4376938ffcbd23c42d_r.png&&&p&可以看到虽然很多细节都和原始图片不一样,不过看上去很和谐,并且细节的丰富程度远胜于SRResNet。这些栩栩如生的细节,可以看作是GAN根据学习到的分布信息“联想”出来的。&/p&&p&对于更看重“看上去好看”的超分辨率应用,SRGAN显然是很合适的。当然对于一些更看重重建指标的应用,比如超分辨率恢复嫌疑犯面部细节,SRGAN就不可以了。&/p&&h2&pix2pix&/h2&&p&虽然专门用了一节讲SRGAN,但本文用的方法其实是pix2pix[5]。这项工作刚在arxiv上发布就引起了不小的关注,它巧妙的利用GAN的框架解决了通用的Image-to-Image translation的问题。举例来说,在不改变分辨率的情况下:把照片变成油画风格;把白天的照片变成晚上;用色块对图片进行分割或者倒过来;为黑白照片上色;…每个任务都有专门针对性的方法和相关研究,但其实总体来看,都是像素到像素的一种映射啊,其实可以看作是一个问题。这篇文章的巧妙,就在于提出了pix2pix的方法,一个框架,解决所有这些问题。方法的示意图如下:&/p&&p&&img src=&/v2-e2ea753b7b0d7f18abee3_b.png& data-rawwidth=&485& data-rawheight=&437& class=&origin_image zh-lightbox-thumb& width=&485& data-original=&/v2-e2ea753b7b0d7f18abee3_r.png&&就是一个Conditional GAN,条件C是输入的图片。除了直接用C-GAN,这项工作还有两个改进:&/p&&p&1)&b&利用U-Net结构生成细节更好的图片&/b&[6]&/p&&img src=&/v2-beb074bebbfa0db_b.png& data-rawwidth=&907& data-rawheight=&612& class=&origin_image zh-lightbox-thumb& width=&907& data-original=&/v2-beb074bebbfa0db_r.png&&&p&U-Net是德国Freiburg大学模式识别和图像处理组提出的一种全卷积结构。和常见的先降采样到低维度,再升采样到原始分辨率的编解码(Encoder-Decoder)结构的网络相比,U-Net的区别是加入skip-connection,对应的feature maps和decode之后的同样大小的feature maps按通道拼(concatenate)一起,用来保留不同分辨率下像素级的细节信息。U-Net对提升细节的效果非常明显,下面是pix2pix文中给出的一个效果对比:&/p&&p&&img src=&/v2-2fb4ddb2fdc24eea31eea_b.png& data-rawwidth=&563& data-rawheight=&307& class=&origin_image zh-lightbox-thumb& width=&563& data-original=&/v2-2fb4ddb2fdc24eea31eea_r.png&&可以看到,各种不同尺度的信息都得到了很大程度的保留。&/p&&p&2)&b&利用马尔科夫性的判别器(PatchGAN)&br&&/b&&/p&&p&pix2pix和SRGAN的一个异曲同工的地方是都有用重建解决低频成分,用GAN解决高频成分的想法。在pix2pix中,这个思想主要体现在两个地方。一个是loss函数,加入了L1 loss用来让生成的图片和训练的目标图片尽量相似,而图像中高频的细节部分则交由GAN来处理:&/p&&img src=&/v2-cb180ad03d8a72e7883285b_b.png& data-rawwidth=&447& data-rawheight=&51& class=&origin_image zh-lightbox-thumb& width=&447& data-original=&/v2-cb180ad03d8a72e7883285b_r.png&&&p&还有一个就是&b&PatchGAN&/b&,也就是具体的GAN中用来判别是否生成图的方法。PatchGAN的思想是,既然GAN只负责处理低频成分,那么判别器就没必要以一整张图作为输入,只需要对NxN的一个图像patch去进行判别就可以了。这也是为什么叫Markovian discriminator,因为在patch以外的部分认为和本patch互相独立。&/p&&p&具体实现的时候,作者使用的是一个NxN输入的全卷积小网络,最后一层每个像素过sigmoid输出为真的概率,然后用BCEloss计算得到最终loss。这样做的好处是因为输入的维度大大降低,所以参数量少,运算速度也比直接输入一张快,并且可以计算任意大小的图。作者对比了不同大小patch的结果,对于256x256的输入,patch大小在70x70的时候,从视觉上看结果就和直接把整张图片作为判别器输入没什么区别了:&/p&&img src=&/v2-5172ca51efb4ee3e453b15_b.png& data-rawwidth=&842& data-rawheight=&107& class=&origin_image zh-lightbox-thumb& width=&842& data-original=&/v2-5172ca51efb4ee3e453b15_r.png&&&h2&生成带局部马赛克的训练数据&/h2&&p&利用pix2pix,只要准备好无码和相应的有码图片就可以训练去马赛克的模型了,就是这么简单。那么问题是,如何生成有马赛克的图片?&/p&&p&有毅力的话,可以手动加马赛克,这样最为精准。这节介绍一个不那么准,但是比随机强的方法:利用分类模型的激活区域进行自动马赛克标注。&/p&&p&基本思想是利用一个可以识别需要打码图像的分类模型,提取出这个模型中对应类的CAM(&b&C&/b&lass &b&A&/b&ctivation &b&M&/b&ap)[7],然后用马赛克遮住响应最高的区域即可。这里简单说一下什么是CAM,对于最后一层是全局池化(平均或最大都可以)的CNN结构,池化后的feature map相当于是做了个加权相加来计算最终的每个类别进入softmax之前的激活值。CAM的思路是,把这个权重在池化前的feature map上按像素加权相加,最后得到的单张的激活图就可以携带激活当前类别的一些位置信息,这相当于一种弱监督(classification--&localization):&/p&&p&&img src=&/v2-fd28f0b871bd_b.png& data-rawwidth=&660& data-rawheight=&314& class=&origin_image zh-lightbox-thumb& width=&660& data-original=&/v2-fd28f0b871bd_r.png&&上图是一个CAM的示意,用澳洲梗类别的CAM,放大到原图大小,可以看到小狗所在的区域大致是激活响应最高的区域。&/p&&p&那么就缺一个可以识别XXX图片的模型了,网上还恰好就有个现成的,yahoo于2016年发布的开源色情图片识别模型Open NSFW(&b&N&/b&ot &b&S&/b&afe &b&F&/b&or &b&W&/b&ork):&/p&&a href=&/?target=https%3A///yahoo/open_nsfw& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&yahoo/open_nsfw&i class=&icon-external&&&/i&&/a&&p&CAM的实现并不难,结合Open NSFW自动打码的代码和使用放在了这里:&/p&&a href=&/?target=https%3A///frombeijingwithlove/dlcv_for_beginners/tree/master/random_bonus/generate_mosaic_for_porno_images& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&给XX图片生成马赛克&i class=&icon-external&&&/i&&/a&&br&&br&(成功打码的)效果差不多是下面这样子:&img src=&/v2-cbefa39dc983f2645dd8_b.png& data-rawwidth=&768& data-rawheight=&256& class=&origin_image zh-lightbox-thumb& width=&768& data-original=&/v2-cbefa39dc983f2645dd8_r.png&&&h2&去除(爱情)动作片中的马赛克&/h2&&p&这没什么好说的了,一行代码都不用改,只需要按照前面的步骤把数据准备好,然后按照pix2pix官方的使用方法训练就可以了:&/p&&p&Torch版pix2pix:&a href=&/?target=https%3A///phillipi/pix2pix& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&phillipi/pix2pix&i class=&icon-external&&&/i&&/a&&/p&&p&pyTorch版pix2pix(Cycle-GAN二合一版):&a href=&/?target=https%3A///junyanz/pytorch-CycleGAN-and-pix2pix& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&junyanz/pytorch-CycleGAN-and-pix2pix&i class=&icon-external&&&/i&&/a&&/p&&p&从D盘里随随便便找了几千张图片,用来执行了一下自动打码和pix2pix训练(默认参数),效果是下面这样:&/p&&br&&img src=&/v2-9f52b17c0e1296767cbfbfafc290a5bd_b.png& data-rawwidth=&814& data-rawheight=&691& class=&origin_image zh-lightbox-thumb& width=&814& data-original=&/v2-9f52b17c0e1296767cbfbfafc290a5bd_r.png&&&p&什么?你问说好给女优去马赛克呢?女优照片呢?&/p&&img src=&/v2-480fb8a4dcfc7a4f92ec_b.png& data-rawwidth=&75& data-rawheight=&60& class=&content_image& width=&75&&&p&还是要说一下,在真人照片上的效果比蘑菇和花强。&/p&&h2&对偶学习(Dual Learning)&/h2&&p&去马赛克已经讲完了,接下来就是给女孩穿(tuo)衣服了,动手之前,还是先讲一下铺垫:&b&对偶学习&/b&和&b&Cycle-GAN&/b&。&/p&&p&对偶学习是MSRA于2016年提出的一种用于机器翻译的增强学习方法[8],目的是解决海量数据配对标注的难题,个人觉得算是一种弱监督方法(不过看到大多数文献算作无监督)。以机器翻译为例,对偶学习基本思想如下图[9]:&/p&&img src=&/v2-c4b1eeda364fb6c9bada02f3_b.png& data-rawwidth=&866& data-rawheight=&399& class=&origin_image zh-lightbox-thumb& width=&866& data-original=&/v2-c4b1eeda364fb6c9bada02f3_r.png&&左边的灰衣男只懂英语,右边的黑衣女只懂中文,现在的任务就是,要学习如何翻译英语到中文。对偶学习解决这个问题的思路是:给定一个模型&img src=&/equation?tex=f%3Ax%5Crightarrow+y& alt=&f:x\rightarrow y& eeimg=&1&&一上来无法知道f翻译得是否正确,但是如果考虑上&img src=&/equation?tex=f& alt=&f& eeimg=&1&&的对偶问题&img src=&/equation?tex=g%3Ay%5Crightarrow+x& alt=&g:y\rightarrow x& eeimg=&1&&,那么我可以尝试翻译一个英文句子到中文,再翻译回来。这种转了一圈的结果&img src=&/equation?tex=x%27%3Dg%28f%28x%29%29& alt=&x'=g(f(x))& eeimg=&1&&,灰衣男是可以用一个标准(BLEU)判断x'和x是否一个意思,并且把结果的一致性反馈给这两个模型进行改进。同样的,从中文取个句子,这样循环翻译一遍,两个模型又能从黑衣女那里获取反馈并改进模型。其实这就是强化学习的过程,每次翻译就是一个action,每个action会从环境(灰衣男或黑衣女)中获取reward,对模型进行改进,直至收敛。&p&也许有的人看到这里会觉得和上世纪提出的Co-training很像,这个在知乎上也有讨论:&/p&&a href=&/question/& class=&internal&&如何理解刘铁岩老师团队在NIPS 2016上提出的对偶学习(Dual Learning)?&/a&&p&个人觉得还是不一样的,Co-Training是一种multi-view方法,比如一个输入x,如果看作是两个拼一起的特征&img src=&/equation?tex=x%3D%28x_1%2Cx_2%29& alt=&x=(x_1,x_2)& eeimg=&1&&,并且假设&img src=&/equation?tex=x_1& alt=&x_1& eeimg=&1&&和&img src=&/equation?tex=x_2& alt=&x_2& eeimg=&1&&互相独立,那么这时候训练两个分类器&img src=&/equation?tex=f_1%28%5Ccdot%29& alt=&f_1(\cdot)& eeimg=&1&&和&img src=&/equation?tex=f_2%28%5Ccdot%29& alt=&f_2(\cdot)& eeimg=&1&&对于任意样本x应该有&img src=&/equation?tex=f_1%28x_1%29%3Df_2%28x_2%29& alt=&f_1(x_1)=f_2(x_2)& eeimg=&1&&。这对没有标注的样本是很有用的,相当于利用了同一个样本分类结果就应该一样的隐含约束。所以Co-Training的典型场景是少量标注+大量未标注的半监督场景。并且&img src=&/equation?tex=f_1& alt=&f_1& eeimg=&1&&和&img src=&/equation?tex=f_2& alt=&f_2& eeimg=&1&&其实是两个不同,但是domain指向相同的任务。而Dual Learning中&img src=&/equation?tex=f& alt=&f& eeimg=&1&&和&img src=&/equation?tex=g& alt=&g& eeimg=&1&&是对偶任务,利用的隐含约束是&img src=&/equation?tex=x%5Crightarrow+y%5Crightarrow+x& alt=&x\rightarrow y\rightarrow x& eeimg=&1&&的cycle consistency。对输入的特征也没有像Co-Training有那么明确的假设,学习方法上也不一样,Dual Learning算是强化学习。&/p&&h2&CycleGAN和未配对图像翻译(Unpaired Image-to-Image Translation)&/h2&&p&CycleGAN,翻译过来就是:轮着干,是结合了对偶学习和GAN一个很直接而巧妙的想法[10],示意图如下:&/p&&img src=&/v2-9e7396ebccb7c42302fc97_b.png& data-rawwidth=&838& data-rawheight=&216& class=&origin_image zh-lightbox-thumb& width=&838& data-original=&/v2-9e7396ebccb7c42302fc97_r.png&&&p&X和Y分别是两种不同类型图的集合,比如穿衣服的女优和没穿衣服的女优。所以给定一张穿了衣服的女优,要变成没穿衣服的样子,就是个图片翻译问题。CycleGAN示意图中(b)和(c)就是Dual Learning:&/p&&img src=&/v2-de51cac58b_b.png& data-rawwidth=&347& data-rawheight=&62& class=&content_image& width=&347&&&p&在Dual Learning基础上,又加入了两个判别器&img src=&/equation?tex=D_X& alt=&D_X& eeimg=&1&&和&img src=&/equation?tex=D_Y& alt=&D_Y& eeimg=&1&&用来进行对抗训练,让翻译过来的图片尽量逼近当前集合中的图片:&/p&&p&&img src=&/v2-e0ea7a6b38bf2a20cea4ea6f741a4c67_b.png& data-rawwidth=&442& data-rawheight=&59& class=&origin_image zh-lightbox-thumb& width=&442& data-original=&/v2-e0ea7a6b38bf2a20cea4ea6f741a4c67_r.png&&全考虑一起,最终的loss是:&/p&&p&&img src=&/v2-e6d99e7edea969da3dad_b.png& data-rawwidth=&357& data-rawheight=&87& class=&content_image& width=&357&&也许有人会问,那不加cycle-consistency,直接用GAN学习一个&img src=&/equation?tex=X%5Crightarrow+Y& alt=&X\rightarrow Y& eeimg=&1&&的映射,让生成的Y的样本尽量毕竟Y里本身的样本可不可以呢?这个作者在文中也讨论了,会产生GAN训练中容易发生的mode collapse问题。mode collapse问题的一个简单示意如下[1]:&/p&&p&&img src=&/v2-309fce6329592babb784ed_b.png& data-rawwidth=&842& data-rawheight=&262& class=&origin_image zh-lightbox-thumb& width=&842& data-original=&/v2-309fce6329592babb784ed_r.png&&上边的是真实分布,下边的是学习到的分布,可以看到学习到的分布只是完整分布的一部分,这个叫做partial mode collapse,是训练不收敛情况中常见的一种。如果是完全的mode collapse,就是说生成模型得到的都是几乎一样的输出。而加入Cycle-consistency会让一个domain里不同的样本都尽量映射到另一个domain里不同的地方,理想情况就是双射(bijection)。直观来理解,如果通过&img src=&/equation?tex=X%5Crightarrow+Y& alt=&X\rightarrow Y& eeimg=&1&&都映射在Y中同一个点,那么这个点y通过&img src=&/equation?tex=Y%5Crightarrow+X& alt=&Y\rightarrow X& eeimg=&1&&映射回来显然不可能是多个不同的x,所以加入cycle-consistency就帮助避免了mode collapse。这个问题在另一篇和CycleGAN其实本质上没什么不同的方法DiscoGAN中有更详细的讨论[11],有兴趣的话可以参考。&/p&&br&&p&有一点值得注意的是,虽然名字叫CycleGAN,并且套路也和C-GAN很像,但是其实只有adversarial,并没有generative。因为严格来说只是学习了&img src=&/equation?tex=X%5Crightarrow+Y& alt=&X\rightarrow Y& eeimg=&1&&和&img src=&/equation?tex=Y%5Crightarrow+X& alt=&Y\rightarrow X& eeimg=&1&&的mapping,所谓的generative network里并没有随机性。有一个和CycleGAN以及DiscoGAN其实本质上也没什么不同的方法叫DualGAN[12],倒是通过dropout把随机性加上了。不过所有加了随机性产生的样本和原始样本间的cycle-consistency用的还是l1 loss,总觉得这样不是很对劲。当然现在GAN这么热门,其实只要是用了adversarial loss的基本都会取个名字叫XXGAN,也许是可以增加投稿命中率。&/p&&p&另外上节中提到了Co-Training,感觉这里也应该提一下CoGAN[13],因为名字有些相似,并且也可以用于未配对的图像翻译。CoGAN的大体思想是:如果两个Domain之间可以互相映射,那么一定有一些特征是共有的。比如男人和女人,虽然普遍可以从长相区分,但不变的是都有两个眼睛一个鼻子一张嘴等等。所以可以在生成的时候,把生成共有特征和各自特征的部分分开,示意图如下:&br&&/p&&p&&img src=&/v2-57eaadc8cec5190bfd30_b.png& data-rawwidth=&758& data-rawheight=&207& class=&origin_image zh-lightbox-thumb& width=&758& data-original=&/v2-57eaadc8cec5190bfd30_r.png&&其实就是两个GAN结构,其中生成网络和判别网络中比较高层的部分都采用了权值共享(虚线相连的部分),没有全职共享的部分分别处理不同的domain。这样每次就可以根据训练的domain生成一个样本在两个domain中不同的对应,比如戴眼镜和没戴眼镜:&/p&&p&&img src=&/v2-356a6118ccf3e8e3bf1c7_b.png& data-rawwidth=&791& data-rawheight=&267& class=&origin_image zh-lightbox-thumb& width=&791& data-original=&/v2-356a6118ccf3e8e3bf1c7_r.png&&分别有了共有特征和各自domain特征,那么做mapping的思路也就很直接了[14]:&/p&&p&&img src=&/v2-8ac50600e40feaac345e09bd7e05a83d_b.png& data-rawwidth=&771& data-rawheight=&210& class=&origin_image zh-lightbox-thumb& width=&771& data-original=&/v2-8ac50600e40feaac345e09bd7e05a83d_r.png&&在GAN前边加了个domain encoder,然后对每个domain能得到三种样本给判别器区分:直接采样,重建采样,从另一个domain中transfer后的重建采样。训练好之后,用一个domain的encoder+另一个domain的generator就很自然的实现了不同domain的转换。用在图像翻译上的效果如下:&/p&&p&&img src=&/v2-612e9cf5e125fd626be7db_b.png& data-rawwidth=&444& data-rawheight=&544& class=&origin_image zh-lightbox-thumb& width=&444& data-original=&/v2-612e9cf5e125fd626be7db_r.png&&还有个巧妙的思路,是把CoGAN拆开,不同domain作为C-GAN条件的更加显式的做法[15]:&/p&&br&&p&&img src=&/v2-ddec16d502c94f91ea35_b.png& data-rawwidth=&883& data-rawheight=&398& class=&origin_image zh-lightbox-thumb& width=&883& data-original=&/v2-ddec16d502c94f91ea35_r.png&&第一步用噪声Z作为和domain无关的共享表征对应的latent noise,domain信息作为条件C训练一个C-GAN。第二步,训练一个encoder,利用和常见的encode-decode结构相反的decode(generate)-encode结构。学习好的encoder可以结合domain信息,把输入图像中和domain无关的共享特征提取出来。第三步,把前两步训练好的encoder和decoder(generator)连一起,就可以根据domain进行图像翻译了。&/p&&p&CoGAN一系的方法虽然结构看起来更复杂,但个人感觉理解起来要比dual系的方法更直接,并且有latent space,可解释性和属性对应也好一些。&/p&&p&又扯远了,还是回到正题:&/p&&br&&h2&给女优穿上衣服&/h2&&p&其实同样没什么好说的,Cycle-GAN和pix2pix的作者是一拨人,文档都写得非常棒,准备好数据,分成穿衣服的和没穿衣服的两组,按照文档的步骤训练就可以:&/p&&p&Torch版Cycle-GAN:&a href=&/?target=https%3A///junyanz/CycleGAN& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&junyanz/CycleGAN&i class=&icon-external&&&/i&&/a&&/p&&p&pyTorch版Cycle-GAN(pix2pix二合一版):&a href=&/?target=https%3A///junyanz/pytorch-CycleGAN-and-pix2pix& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&junyanz/pytorch-CycleGAN-and-pix2pix&i class=&icon-external&&&/i&&/a&&/p&&p&Cycle-GAN收敛不易,我用了128x128分辨率训练了穿衣服和没穿衣服的女优各一千多张,同样是默认参数训练了120个epoch,最后小部分成功“穿衣服”的结果如下:&/p&&img src=&/v2-fee34d66c386e0e01e5804_b.jpg& data-rawwidth=&1117& data-rawheight=&192& class=&origin_image zh-lightbox-thumb& width=&1117& data-original=&/v2-fee34d66c386e0e01e5804_r.jpg&&&img src=&/v2-de57c5ebefa4251ee3caa1_b.jpg& data-rawwidth=&1117& data-rawheight=&192& class=&origin_image zh-lightbox-thumb& width=&1117& data-original=&/v2-de57c5ebefa4251ee3caa1_r.jpg&&&p&虽然都有些突兀,但好歹是穿上衣服了。注意马赛克不是图片里就有的,是我后来加上去的。&/p&&p&那么,脱衣服的例子在哪里?&/p&&img src=&/v2-480fb8a4dcfc7a4f92ec_b.png& data-rawwidth=&75& data-rawheight=&60& class=&content_image& width=&75&&&h2&参考文献&/h2&&p&[1] I. Goodfellow. Nips 2016 tutorial: Generative adversarial networks. arXiv preprint arXiv:, 2016.&/p&&p&[2] A. B. L. Larsen, S. K. S?nderby, Generating Faces with Torch. &a href=&/?target=http%3A//torch.ch/blog//gan.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Torch | Generating Faces with Torch&i class=&icon-external&&&/i&&/a&&/p&&p&[3] A. B. L. Larsen, S. K. S?nderby, H. Larochelle, and O. Winther. Autoencoding beyond pixels using a
learned similarity metric. In ICML, pages , 2016.
&/p&&p&[4] C. Ledig, L. Theis, F. Huszar, J. Caballero, A. Aitken, A. Tejani, J. Totz, Z. Wang, and W. Shi. Photo-realistic single image super-resolution using a generative adversarial network. arXiv:, 2016.&/p&&p&[5] P. Isola, J.-Y. Zhu, T. Zhou, and A. A. Efros. Image-to-image translation with conditional adversarial networks. arxiv, 2016. &/p&&p&[6] O. Ronneberger, P. Fischer, and T. Brox. U-net: Convolutional networks for biomedical image segmentation. In MICCAI, pages 234–241. Springer, 2015.&/p&&p&[7] B. Zhou, A. Khosla, A. Lapedriza, A. Oliva, and A. Torralba. Learning deep features for discriminative localization. arXiv preprint arXiv:, 2015.&/p&&p&[8] He, D., Xia, Y., Qin, T., Wang, L., Yu, N., Liu, T.-Y., and Ma, W.-Y. (2016a). Dual learning for machine translation. In the Annual Conference on Neural Information Processing Systems (NIPS), 2016.&/p&&br&&p&[9] &a href=&/?target=http%3A//www.dsrg.stuorg.iastate.edu/wp-content/uploads/2017/02/dual-learning_-pushing-the-new-frontier-of-artificial-intelligence-tieyan-liu.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&& Tie-Yan Liu, Dual Learning: Pushing the New Frontier of Artificial Intelligence, MIFS 2016&i class=&icon-external&&&/i&&/a&&br&&/p&&p&[10] J.-Y. Zhu, T. Park, P. Isola, and A. A. Efros. Unpaired image-to-image translation using cycle-consistent adversarial networkss. arXiv preprint arXiv:, 2017.&/p&&p&[11] T. Kim, M. Cha, H. Kim, J. Lee, and J. Kim. Learning to Discover Cross-Domain Relations with Generative Adversarial Networks. ArXiv e-prints, Mar. 2017.&/p&&br&&p&[12] Z. Yi, H. Zhang, P. T. Gong, et al. DualGAN: Unsupervised dual learning for image-to-image translation. arXiv preprint arXiv:, 2017.&/p&&br&&p&[13] M.-Y. Liu and O. Tuzel. Coupled generative adversarial networks. In Advances in Neural Information Processing Systems (NIPS), 2016.&/p&&p&[14] M.-Y. Liu, T. Breuel, and J. Kautz. Unsupervised image-to-image translation networks. arXiv preprint arXiv:, 2017.&/p&&p&[15] Dong, H., Neekhara, P., Wu, C., Guo, Y.: Unsupervised image-to-image translation with generative adversarial networks. arXiv preprint arXiv:, 2017.&/p&&p&=========== 分割线: ===========&/p&&p&上周日发的时候也想到了可能会有许多人对这个话题感兴趣,但没想到超过了1.5W赞这么多,大概看了看评论,做一些补充:&/p&&p&&b&1) &/b&马赛克训练数据:对于一般的机器学习问题,都是分布越简单越容易,遵循这个原则,我用的约束是单人照片,具体方法是:先找一个Pascal VOC训练好的SSD代码,然后SSD筛选了一批每张图里只能检测到一个人的。&/p&&p&最后在真人照片上的效果看上去还是不错的,我没有做过量化评估,大体来说看上去挺像的要超过一半,非常逼真的可能有5%~10%。两人以上战斗的动作画面我没有评估过。&/p&&p&&b&2)&/b&穿(tuo)衣训练数据:因为收敛很难,所以数据的加了更多约束:只用女性单人正面照片。同样通过SSD检测出单人照片,同时考虑person框的宽高比小于1的且框内能检测到人脸的(OpenCV的人脸检测)。这样尽量筛选出一批面向镜头,身体占画面比接近的照片。&/p&&p&最后的效果我在原文中也提到过,只有小部分能成功穿上(tuo)衣服,具体我也没有量化统计过,大概100张里两三张吧,大部分都是身上出现了看上去有点像衣服的线条或是另一个人的胸部。考虑到我最后筛选出的图片人物占画面比仍然有很大的变化,很可能我的模型就是遇到了文中提到的partial mode collapse的问题。&/p&&p&如果有更好的办法筛选出人物大小差不多的照片,效果应该能提升不少。比如我在用SSD筛选的时候如果考虑宽高比更小一些,筛选出的照片看上去会更加一致,不过我资源不太够,这样做后训练集就只有不到300张,资源够的老司机们有兴趣可以试试。&/p&&br&&p&&b&3)&/b&预训练模型有没有?有,但是我研读了中华人民共和国刑法第三百六十三、三百六十四和三百六十六条,完全读不懂,所以还是不提供。再说就算我提供了,根据1)和2),看到你想看的内容也是需要运气的。&/p&&p&另外特别感谢赞赏的知友们,这篇文章是想说&b&书中自有颜如玉&/b&,而知友们的赞赏让我知道&b&书中真有黄金屋&/b&,古人诚不我欺…&/p&
作为一名久经片场的老司机,早就想写一些探讨驾驶技术的文章。这篇就介绍利用生成式对抗网络(GAN)的两个基本驾驶技能: 1) 去除(爱情)动作片中的马赛克2) 给(爱情)动作片中的女孩穿(tuo)衣服 生成式模型上一篇《》中已经简单介…
&img src=&/50/v2-2c0bdee7ad348_b.jpg& data-rawwidth=&400& data-rawheight=&267& class=&content_image& width=&400&&&h3&前言&br&&/h3&
&p&Lamport老爷子在这篇著名的论文中探讨了分布式系统中事件和时间的关系,并且以数学家的最敏锐的嗅觉抓住了分布式系统中的本质问题,同时引入逻辑时钟,为以后的分布式系统设计点亮了指路明灯。&/p&
&h4&事件&/h4&
&p&事件是驱动万物演化的根本动力。事件包含其内在的一系列行为以及这些行为而产生的影响,而这些影响又可能触发下一个事件。在这绵延不断的事件链条中,周围的世界处于一刻不停的变化之中。一件极其微小的事件可能产生巨大的连锁反应,蝴蝶效应说的便是这个道理。&/p&
&h4&时间&/h4&
&p&时间是什么,没几个人真正理解。不妨将时间和事件联系起来,我们便会产生直观而具体的感受。我们是无法感受时间的,也无法测量时间,我们感知的时间其实是事件的流逝,比如看到太阳升起我们知道是早晨,而落日则意味着傍晚。&/p&
&p&时间有众多的计量方法:比如古人的日晷,再到现在的原子时钟。所有计时方法的本质在于记事。因此,时间和事件本就合二为一。&/p&
分布式系统
&p&在我看来,这个世界就是一个分布式系统。区别的只是系统的规模。&/p&
&p&搞计算机的眼里几台服务器组成的系统就是分布式系统,生物学家眼里某个种群构成了一个分布式系统,而在外眼里,整个世界是一个分布式系统。&/p&
&p&分布式系统最核心的问题是什么?信息交互!为什么在上面提到的不同的学者关注不同的分布式系统呢?这是因为这些系统之间难以存在信息流通。例如,目前阶段一台计算机很难和一头大象交流。而计算机之间则很容易信息交互。&/p&
&p&信息又是什么?信息是载体,它是事件绵延不断传播的源动力。没有了信息,事件便成为孤单的粒子。因此,可以毫不夸张的说,信息是发展的源动力。&/p&
&p&分布式系统的难点在于分布式。分布式带来的头疼问题是信息交互的延迟、丢失、乱序等一系列问题。受限于光速限制,任何信息的传播都需要一定的时间,哪怕再短。&/p&
&p&而信息交互的延迟、丢失、乱序等问题则进一步体现在事件的影响上。信息的延迟可能导致事件发生的延迟,信息的丢失导致事件根本不会被处罚、信息的乱序则可能导致事件错乱。而这些看似偶然事件错乱则可能会给大千世界的演化带来极其深刻的影响。&/p&
&h4&事件序列&/h4&
&p&其实文章的核心在于讨论事件序列。事件序列指的是特定环境中的事件发生的先后顺序。时间只不过是事件序列的一种定义方法。即使是用时间来定义,也存在物理时间、逻辑时间等等方法。&/p&
&p&一个分布式系统由众多独立的个体组成,称之为Process,每个个体的事件来源有两类:&/p&
&ul&&li&内部事件:此类事件由个体内部产生,可以认为与其他个体不产生关联;&/li&&li&外部事件:此类事件由其他个体刺激本个体产生,这种刺激的表现形式是消息。&/li&&/ul&&p&事件序列有两种:偏序事件序列和全序事件序列。&/p&
&p&&strong&偏序&/strong&&/p&
&p&所谓的偏序指的是只能为系统中的部分事件定义先后顺序。这里的部分其实是有因果关系的事件。&/p&
&p&例如,发生在个体PA的一个事件E1,该事件的影响是产生了消息M,M传播至个体B,进而导致事件E2的发生,即说明E1-&E2:因为E1而导致了E2的产生。而对于两个相互独立的事件,我们无法从原理上判断孰先孰后。&/p&
&p&偏序的严格定义,偏序以符号-&代替:&/p&
&blockquote&&ul&&li&在同一个Process内部,如果事件a早于事件b发生,称为a-&b;&/li&&li&如果a和b是两个不同Process的事件,且b是a发送的消息的接收者,同样 a-&b;&/li&&li&如果a-&b,b-&c,那么a-&c。&/li&&/ul&&/blockquote&
&p&这个定义很容易理解。&/p&
&p&Lamport在论文中提出了一种利用逻辑时间设计的一种偏序系统方法:&/p&
&blockquote&&ul&&li&每个Process存在独立的事件序列发生器,每次产生新的事件,该序列发生器自增1,并将结果赋予该事件;&/li&&li&如果Process的事件E需要向其他Process发送消息M,那么在M中携带E的序列号;&/li&&li&如果Process收到外部消息M,获取M中携带的序列号,与自身的事件序列发生器取最大值,然后自增1,赋给由于M而触发的新的外部事件。&/li&&/ul&&/blockquote&
&p&根据上面的定义,我们可以得到如下结论:&/p&
&blockquote&&ul&&li&Process内部的事件均可以比较先后顺序;&/li&&li&Process之间的因果事件可以确定先后顺序,而Process之间的独立事件则无法比较。&/li&&/ul&&/blockquote&
&figure&&img src=&/v2-deac32bfea4a243f7ecd76cb0d009528_b.png& data-rawwidth=&328& data-rawheight=&268& class=&content_image& width=&328&&&/figure&&p&例如: &br&
上图中的p1-&r4成立,因为有:p1-&q2,q2-&q3,q3-&q4,q4-&r3,r3-&r4。 &br&
而p3-&q3则不成立。&/p&
&p&真实世界其实是一个偏序系统,记住,物理时间是不准确的。&/p&
&p&&strong&全序&/strong&&/p&
&p&全序是指所有的事件都可以区分先后顺序。无论是真实或是虚拟世界,这都是受欢迎的。因为,所有的事件都有了一个统一的评判标准,我们一直欢迎统一而拒绝分裂。&/p&
&p&在偏序的基础上,Lamport定义了一种全序方案,在偏序的基础上有所增强:&/p&
&blockquote&&p&每个事件表示为一个三元组:&E, C, P&&/p&
&/blockquote&
&p&其中:&/p&
&ul&&li&E:代表事件;&/li&&li&C:代表事件所发生的Process赋予该事件的序列号(逻辑时间);&/li&&li&P:代表事件所发生的Process的编号&/li&&/ul&&p&有了该三元组后,定义事件先后的顺序就变成了:&/p&
&blockquote&&p&如果C(i, a) & C(j, b)
&br&&strong&或者&/strong& &br&
如果C(i, a) = C(j, b)并且P(i) & P(j)&/p&
&/blockquote&
&p&&strong&通过事件序解决特定问题&/strong&&/p&
&p&做着费尽心思定义了偏序和全序,接下来就看它如何帮助解决实际问题。例如,有这样一个共享资源分配问题:&/p&
&blockquote&&p&多个Process共享一个集中资源R,每个Process想使用R时必须申请,经过全部人同意后才可以使用,且使用完成后必须要释放R以供他人使用。且需要满足先申请先访问原则,还不能存在死锁的问题。&/p&
&/blockquote&
&p&很容易想到的是使用协调者的解决方法:&/p&
&blockquote&&ul&&li&存在一个至高无上的协调者管理资源分配;&/li&&li&协调者根据收到请求的先后顺序分配资源的使用顺序;&/li&&/ul&&/blockquote&
&p&这个方案看起来一切正常,但是可能存在一个漏洞,假如:&/p&
&blockquote&&ol&&li&Process 1向协调者发起资源分配请求R1;&/li&&li&Process 1向Process2发消息M;&/li&&li&M触发Process 2产生事件,该事件也向协调者发起资源分配请求R2;&/li&&li&R2先于R1到达协调者&/li&&/ol&&/blockquote&
&p&于是就不满足上面的先申请先访问的原则了。&/p&
&p&Lamport提出的方案:&/p&
&blockquote&&ul&&li&去掉协调者,改用分布式协调方案;&/li&&li&每个Process均有一个队列维护资源申请的消息,成为RequestQueue&/li&&li&P申请资源时,向其他Process广播该资源申请消息,该消息是一个三元组&T, P, Action&;&/li&&li&P收到其他Process的资源申请消息时,将该消息放置于RequestQueue的尾部,并给申请者回复ACK消息;&/li&&/ul&&/blockquote&
&figure&&img src=&/v2-df6aaef8be14_b.png& data-rawwidth=&566& data-rawheight=&278& class=&origin_image zh-lightbox-thumb& width=&566& data-original=&/v2-df6aaef8be14_r.png&&&/figure&&p&而Pi判断某个消息(其实代表了一个事件,因为一般是事件申请资源访问,而消息只不过是代替事件去获得访问权限)能否获得资源的访问权限的条件:&/p&
&blockquote&&ul&&li&该消息获得了所有节点的ACK;&/li&&li&在本地的消息队列中没有比该消息更早的消息。&/li&&/ul&&/blockquote&
&p&我们仔细品味下这两个条件:&/p&
&blockquote&&ul&&li&获得所有节点的ACK这个比较容易理解,只有大家都同意了才可以访问;&/li&&li&没有比该消息更早的消息则表示该消息是最早的申请者,注意,本地的消息队列中不仅有自己发出的资源申请访问的请求消息,还存有其他节点的资源申请访问请求;&/li&&li&如何判断两个消息先后顺序就采用了我们上面的全序定义方案,先判断T,相同时再判断P。&/li&&/ul&&/blockquote&
&p&需要注意的是,本地的Request Queue中保存的请求消息可能会乱序,并非说队列头部是就是就旧的,队列尾部的就是最新的。因为多个节点之间存在消息传递上的延迟,先发出的请求有可能会后到达。因此,在判断时需要遍历队列上的所有消息。&/p&
&p&&strong&物理时钟&/strong&&/p&
&p&论文的这部分未涉猎,因为涉及到很复杂的数学证明。&/p&
&h4&总结&/h4&
&p&如果将这篇论文当作纯技术论文来看,那就大错特错了,论文的背后其实包含了极其深刻的数学和哲学含义,作者看似在说分布式系统,其实可以将其推广到整个世界乃至宇宙。至少,老爷子的这篇文章触发了我重新审视时间和事件这两个概念,特整理出来,与大家分享,希望能互相交流。&/p&
Lamport老爷子在这篇著名的论文中探讨了分布式系统中事件和时间的关系,并且以数学家的最敏锐的嗅觉抓住了分布式系统中的本质问题,同时引入逻辑时钟,为以后的分布式系统设计点亮了指路明灯。
事件是驱动万物演化的根本动力。事件包含其内在…
&img src=&/50/v2-e2dc2d1bb6b44d22c426a1f_b.jpg& data-rawwidth=&701& data-rawheight=&451& class=&origin_image zh-lightbox-thumb& width=&701& data-original=&/50/v2-e2dc2d1bb6b44d22c426a1f_r.jpg&&&p&&b&1:Hadoop VS Spark &/b&&/p&&figure&&img src=&/v2-278aadfb70_b.png& data-rawheight=&161& data-rawwidth=&963& class=&origin_image zh-lightbox-thumb& width=&963& data-original=&/v2-278aadfb70_r.png&&&/figure&&br&&figure&&img src=&/v2-ae5ce3fe8d6b48a8e920b206b7bfb9dc_b.png& data-rawheight=&156& data-rawwidth=&614& class=&origin_image zh-lightbox-thumb& width=&614& data-original=&/v2-ae5ce3fe8d6b48a8e920b206b7bfb9dc_r.png&&&/figure&&p&&b&2.
Hadoop&/b&&b&实时应&/b&&b&用有哪些&/b&&b&?&/b&&/p&&p&Hadoop,众所周知的Apache Hadoop,是一个开放源代码软件平台,用于大容量数据的可扩展和分布式计算。它提供对数字平台和企业内部生成的结构化和非结构化数据的快速,高性能和成本效益的分析。它如今几乎应用在所有部门 。比如:&/p&&p&o交通管理&/p&&p&o流处理&/p&&p&o内容管理和电子邮件存档&/p&&p&o使用Hadoop计算集群处理大鼠脑神经元信号&/p&&p&o欺诈检测和预防&/p&&p&o广告定向平台正在使用Hadoop捕获和分析点击流,事务,视频和社交媒体数据&/p&&p&o在社交媒体平台上管理内容,信息,图片和视频&/p&&p&o实时分析客户数据,以提高业务绩效&/p&&p&o公共部门领域,如情报,国防,网络安全和科学研究&/p&&p&o金融机构正在使用大数据Hadoop来降低风险,分析欺诈模式,识别流氓交易者,更精确地根据客户细分定位营销活动,并提高客户满意度&/p&&p&o访问非结构化数据,例如医疗设备输出,医生笔记,实验室结果,成像报告,医疗通信,临床数据和财务数据。&/p&&p&&b&3. Hadoop与其它计算系统的不同?&/b&&/p&&p&Hadoop是一个分布式文件系统,它允许您在云计算机上存储和处理大量数据,尤其是处理冗余数据。通过这个HDFS内容来了解分布式文件系统的工作原理。 这样最主要好处是,由于数据存储在几个节点中,因此最好以分布式方式处理。 每个节点可以处理存储在其上的数据,省去在网络上移来移去的时间。&/p&&p&相反,在关系数据库计算系统中,你可以实时查询数据,但是当数据庞大时,数据存储并不高效。 &/p&&p&Hadoop还提供了一个使用Hadoop HBase构建列数据库的方案,用于对行运行查询。
&/p&&p&&b&4. Hadoop可以运行在哪些模式中?&/b&&/p&&p&Hadoop可以以三种模式运行:&/p&&p&1.独立模式:Hadoop的默认模式,它使用本地文件系统进行输入和输出操作。 此模式主要用于调试目的,不支持使用HDFS。 此外,在此模式下,不存在mapred-site.xml,core-site.xml,hdfs-site.xml文件所需的自定义配置。 比其他模式更快。&/p&&p&2.伪分布模式(单节点群集):在这种模式下,需要配置上述所有三个文件,所有守护程序都在一个节点上运行,因此,主节点和从节点是相同的。&/p&&p&3.完全分布式模式(多个集群节点):这是Hadoop的生产阶段,其中数据被使用并分布在Hadoop集群上的多个节点上。 单独的节点分配为主服务器和从服务器。&/p&&p&&b&5 HDFS Block和Input Split之间的主要区别&/b&&/p&&p&简单来说,“block”是数据的物理表示,而split是block中存在的数据的逻辑表示。分割作用是block和mapper之间的中介。假设我们有两个block:&/p&&p&block 1:iintteell&/p&&p&block 2:Ii ppaatt&/p&&p&现在,考虑到映射,它将从第一个block读到ll,但不知道如何同时处理第二个block。此时split将发挥它的作用,它将形成逻辑组,即将Block1和Block2的作为一个整块处理。然后使用输入格式和记录读取器形成键值对,并发送映射以进行进一步处理使用输入拆分,如果资源有限,则可以增加拆分大小以限制映射数量。例如,如果有10块640MB(每个64MB)并且资源有限,可以将“分割大小”指定为128MB。这将形成一个128MB的逻辑组,每次只执行5个映射。&/p&&p&然而,如果”分割大小”属性设置为false,整个文件将形成一个输入拆分,并由单个映射处理,当文件较大时,消耗更多的时间。&/p&&p&&b&6.什么是分布式缓存,它有什么好处?&/b&&/p&&p&Hadoop中的分布式缓存是Map-Reduce框架在需要缓存文件时的服务。 &b&&u&点击这里了解MapReduce
&/u&&/b&&b&&u&课程信息。&/u&&/b& 一旦为指定作业缓存文件,hadoop将使其在系统和内存中的每个数据节点上可用,其中map和reduce任务正在执行。然后,可以轻松访问和读取缓存文件并在编码中填充任何集合,比如数组,哈希映射。&/p&&p&使用分布式缓存的好处是:&/p&&p&o它分发简单的只读文本/数据文件和/或复杂类型,如jar,存档和其他。 这些}

我要回帖

更多关于 联通百度大神卡 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信