diff --git a/.github/workflows/hexo.yml b/.github/workflows/hexo.yml new file mode 100644 index 00000000..88b14c91 --- /dev/null +++ b/.github/workflows/hexo.yml @@ -0,0 +1,42 @@ +name: Hexo Blog Deploy + +on: [push] + +jobs: + build: + + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@master + - name: Prepare Node.js + uses: actions/setup-node@v1 + with: + node-version: 10.x + - name: Generate pages + run: | + npm install + ./node_modules/hexo/bin/hexo clean + ./node_modules/hexo/bin/hexo generate + echo "hexo generate done!" + - name: Deploy + env: + GITHUB_TOKEN: ${{ secrets.BLOG_DEPLOY }} + run: | + REPOSITORY_PATH="https://x-access-token:${GITHUB_TOKEN}@github.com/joeltsui/joeltsui.github.io.git" + + cd public/ + git init + git config user.name "${GITHUB_ACTION}" + git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" + + git remote add origin "${REPOSITORY_PATH}" + git add --all + + echo "Start commit" + git commit --allow-empty -m "Deploy to master" + + echo "Start push" + git push origin master --force + + echo "Finish deploy" + diff --git a/.gitignore b/.gitignore index dd05dde7..221e9fd1 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ node_modules tmp source/CNAME +package-lock.json +db.json +public \ No newline at end of file diff --git a/README.md b/README.md index f9c959c5..066a74cc 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A brand new default theme for [[Hexo](https://hexo.io)]. [Preview](http://cofess.github.io/) | [中文说明文档](README.cn.md) | [iconfont](http://blog.cofess.com/hexo-theme-pure/iconfont/demo_fontclass.html) -![](screenshot/pure.png) +![](themes/pure/screenshot/pure.png) ## Features @@ -14,13 +14,13 @@ A brand new default theme for [[Hexo](https://hexo.io)]. [Preview](http://cofes ## Skins -![](screenshot/pure-theme-black.png) +![](themes/pure/screenshot/pure-theme-black.png) -![](screenshot/pure-theme-blue.png) +![](themes/pure/screenshot/pure-theme-blue.png) -![](screenshot/pure-theme-green.png) +![](themes/pure/screenshot/pure-theme-green.png) -![](screenshot/pure-theme-purple.png) +![](themes/pure/screenshot/pure-theme-purple.png) ## Appearance diff --git a/_config.yml b/_config.yml index 1836723f..99525ed5 100644 --- a/_config.yml +++ b/_config.yml @@ -1,236 +1,101 @@ -# menu -menu: - Home: . - Archives: archives # 归档 - Categories: categories # 分类 - Tags: tags # 标签 - Repository: repository # github repositories - Books: books # 豆瓣书单 - Links: links # 友链 - About: about # 关于 - -# Enable/Disable menu icons -menu_icons: - enable: true # 是否启用导航菜单图标 - home: icon-home-fill - archives: icon-archives-fill - categories: icon-folder - tags: icon-tags - repository: icon-project - books: icon-book-fill - links: icon-friendship - about: icon-cup-fill - -# rss -rss: /atom.xml +# Hexo Configuration +## Docs: https://hexo.io/docs/configuration.html +## Source: https://github.com/hexojs/hexo/ # Site -site: - logo: - enabled: true - width: 40 - height: 40 - url: ../images/logo.png - title: Hexo # 页面title - favicon: /favicon.png - board:

欢迎交流与分享经验!

# 站点公告 - copyright: false # 底部版权信息 - -# config -config: - skin: # 主题颜色 theme-black theme-blue theme-green theme-purple - layout: main-center # 布局方式 main-left main-center main-right - toc: true # 是否开启文章章节目录导航 - menu_highlight: false # 是否开启当前菜单高亮显示 - thumbnail: false # enable posts thumbnail, options: true, false - excerpt_link: Read More - -# Pagination -pagination: - number: false - prev: - alwayShow: true - next: - alwayShow: true - -# Sidebar -sidebar: right -widgets: - - board - - category - - tag - - tagcloud - - archive - - recent_posts - -# display widgets at the bottom of index pages (pagination == 2) -index_widgets: -# - category -# - tagcloud -# - archive - -# widget behavior -archive_type: 'monthly' -show_count: true - -# Fancybox -fancybox: false - -# Search -search: - insight: true # you need to install `hexo-generator-json-content` before using Insight Search - baidu: false # you need to disable other search engines to use Baidu search - -# Donate -donate: +title: 理想国 +subtitle: '一个码农的自留地' +description: '这是一个有趣的世界' +keywords: +author: Joel Tsui +language: zh +timezone: '' + +# URL +## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/' +url: http://joeltsui.github.io +root: / +permalink: :year/:month/:day/:title/ +permalink_defaults: +pretty_urls: + trailing_index: true # Set to false to remove trailing index.html from permalinks + +# Directory +source_dir: source +public_dir: public +tag_dir: tags +archive_dir: archives +category_dir: categories +code_dir: downloads/code +i18n_dir: :lang +skip_render: + +# Writing +new_post_name: :title.md # File name of new posts +default_layout: post +titlecase: false # Transform title into titlecase +external_link: + enable: true # Open external links in new tab + field: site # Apply to the whole site + exclude: '' +filename_case: 0 +render_drafts: false +post_asset_folder: false +relative_link: false +future: true +highlight: enable: true - # 微信打赏 - wechatpay: - qrcode: images/donate/wechatpayimg.png - title: 微信支付 - # 支付宝打赏 - alipay: - qrcode: images/donate/alipayimg.png - title: 支付宝 - -# Share -# weibo,qq,qzone,wechat,tencent,douban,diandian,facebook,twitter,google,linkedin -share: - enable: true # 是否启用分享 - sites: weibo,qq,wechat,facebook,twitter # PC端显示的分享图标 - mobile_sites: weibo,qq,qzone # 移动端显示的分享图标 + line_number: true + auto_detect: false + tab_replace: '' + +# Home page setting +# path: Root path for your blogs index page. (default = '') +# per_page: Posts displayed per page. (0 = disable pagination) +# order_by: Posts order. (Order by date descending by default) +index_generator: + path: '' + per_page: 10 + order_by: -date + +# Category & Tag +default_category: uncategorized +category_map: +tag_map: + +# Metadata elements +## https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta +meta_generator: true + +# Date / Time format +## Hexo uses Moment.js to parse and display date +## You can customize the date format as defined in +## http://momentjs.com/docs/#/displaying/format/ +date_format: YYYY-MM-DD +time_format: HH:mm:ss +## Use post's date for updated date unless set in front-matter +use_date_for_updated: true -# Github -github: - username: cofess # github username - -# Comment -# Gitment -# Introduction: https://imsun.net/posts/gitment-introduction/ -comment: - type: valine # 启用哪种评论系统 - disqus: # enter disqus shortname here - youyan: - uid: 1783844 # enter youyan uid - livere: - uid: # enter youyan uid - gitment: - githubID: - repo: - ClientID: - ClientSecret: - lazy: false - gitalk: # gitalk. https://gitalk.github.io/ - owner: #必须. GitHub repository 所有者,可以是个人或者组织。 - admin: #必须. GitHub repository 的所有者和合作者 (对这个 repository 有写权限的用户)。 - repo: #必须. GitHub repository. - ClientID: #必须. GitHub Application Client ID. - ClientSecret: #必须. GitHub Application Client Secret. - valine: # Valine. https://valine.js.org - appid: # your leancloud application appid - appkey: # your leancloud application appkey - notify: false # mail notifier , https://github.com/xCss/Valine/wiki - verify: false # Verification code - placeholder: Just go go # comment box placeholder - avatar: mm # gravatar style - meta: nick,mail,link # custom comment header - pageSize: 10 # pagination size - visitor: false # Article reading statistic https://valine.js.org/visitor.html - -# douban 豆瓣书单 -# Api: - # https://developers.douban.com/wiki/?title=book_v2 图书 - # https://developers.douban.com/wiki/?title=movie_v2 电影 -# books: - # https://api.douban.com/v2/book/user/:name/collections?start=0&count=100 个人书单列表 -# movies: - # https://api.douban.com/v2/movie/in_theaters 正在上映的电影 - # https://api.douban.com/v2/movie/coming_soon 即将上映的电影 - # https://api.douban.com/v2/movie/subject/:id 单个电影信息 - # https://api.douban.com/v2/movie/search?q={text} 电影搜索 -douban: - user: # 豆瓣用户名 - start: 0 # 从哪一条记录开始 - count: 100 # 获取豆瓣书单数据条数 - -# PV -pv: - busuanzi: - enable: false # 不蒜子统计 - leancloud: - enable: false # leancloud统计 - app_id: # leancloud - app_key: # leancloud - -# wordcount -postCount: - enable: false - wordcount: true # 文章字数统计 - min2read: true # 阅读时长预计 - -# Plugins -plugins: - google_analytics: # enter the tracking ID for your Google Analytics - google_site_verification: # enter Google site verification code - baidu_analytics: # enter Baidu Analytics hash key - tencent_analytics: - -# Miscellaneous -twitter: -google_plus: -fb_admins: -fb_app_id: - -# profile -profile: - enabled: true # Whether to show profile bar - avatar: images/avatar.jpg - gravatar: # Gravatar email address, if you enable Gravatar, your avatar config will be overriden - author: 昵称 - author_title: Web Developer & Designer - author_description: 个人简介。 - location: Shenzhen, China - follow: https://github.com/cofess - # Social Links - social: - links: - github: https://github.com/cofess - weibo: http://weibo.com/cofess - twitter: https://twitter.com/iwebued - # facebook: / - # dribbble: / - behance: https://www.behance.net/cofess - rss: atom.xml - link_tooltip: true # enable the social link tooltip, options: true, false - # My Skills - skills: - Git: ★★★☆☆ - Gulp: ★★★☆☆ - Javascript: ★★★☆☆ - HTML+CSS: ★★★☆☆ - Bootstrap: ★★★☆☆ - ThinkPHP: ★★★☆☆ - 平面设计: ★★★☆☆ - # My Personal Links - links: - Github: https://github.com/cofess - Blog: http://blog.cofess.com - 微博: http://weibo.com/cofess - 花瓣: http://huaban.com/cofess - Behance: https://www.behance.net/cofess - # My Personal Labels - labels: - - 前端 - - 前端开发 - - 前端重构 - - Web前端 - - 网页重构 - # My Personal Works - works: - name: - link: http://www.example.com - date: 2016 - # My Personal Projects - projects: - cofess/gulp-startpro: https://github.com/cofess/gulp-startpro - cofess/hexo-theme-pure: https://github.com/cofess/hexo-theme-pure \ No newline at end of file +# Pagination +## Set per_page to 0 to disable pagination +per_page: 10 +pagination_dir: page + +# Include / Exclude file(s) +## include:/exclude: options only apply to the 'source/' folder +include: +exclude: +ignore: + + +# Extensions +## Plugins: https://hexo.io/plugins/ +## Themes: https://hexo.io/themes/ +theme: pure + +# Deployment +## Docs: https://hexo.io/docs/deployment.html +deploy: + type: 'git' + repo: git@github.com:JoelTsui/joeltsui.github.io.git + branch: master diff --git a/package.json b/package.json index c77a9a11..2ce65fd8 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,27 @@ { - "name": "hexo-theme-pure", - "version": "0.0.1", + "name": "hexo-site", + "version": "0.0.0", "private": true, - "devDependencies": { - + "scripts": { + "build": "hexo generate", + "clean": "hexo clean", + "deploy": "hexo deploy", + "server": "hexo server" + }, + "hexo": { + "version": "4.0.0" + }, + "dependencies": { + "gitalk": "^1.5.0", + "hexo": "^4.0.0", + "hexo-deployer-git": "^2.0.0", + "hexo-generator-archive": "^1.0.0", + "hexo-generator-category": "^1.0.0", + "hexo-generator-index": "^1.0.0", + "hexo-generator-tag": "^1.0.0", + "hexo-renderer-ejs": "^1.0.0", + "hexo-renderer-kramed": "^0.1.4", + "hexo-renderer-stylus": "^1.1.0", + "hexo-server": "^1.0.0" } } diff --git a/scaffolds/draft.md b/scaffolds/draft.md new file mode 100644 index 00000000..498e95ba --- /dev/null +++ b/scaffolds/draft.md @@ -0,0 +1,4 @@ +--- +title: {{ title }} +tags: +--- diff --git a/scaffolds/page.md b/scaffolds/page.md new file mode 100644 index 00000000..f01ba3cd --- /dev/null +++ b/scaffolds/page.md @@ -0,0 +1,4 @@ +--- +title: {{ title }} +date: {{ date }} +--- diff --git a/scaffolds/post.md b/scaffolds/post.md new file mode 100644 index 00000000..1f9b9a46 --- /dev/null +++ b/scaffolds/post.md @@ -0,0 +1,5 @@ +--- +title: {{ title }} +date: {{ date }} +tags: +--- diff --git a/source/_images/2018-04-18-autossh-00.png b/source/_images/2018-04-18-autossh-00.png new file mode 100644 index 00000000..890ebe29 Binary files /dev/null and b/source/_images/2018-04-18-autossh-00.png differ diff --git a/source/_images/2018-08-26-logistic-example-result.png b/source/_images/2018-08-26-logistic-example-result.png new file mode 100644 index 00000000..e4053ccc Binary files /dev/null and b/source/_images/2018-08-26-logistic-example-result.png differ diff --git a/source/_images/2018-08-26-logistic-example.png b/source/_images/2018-08-26-logistic-example.png new file mode 100644 index 00000000..8f3452a4 Binary files /dev/null and b/source/_images/2018-08-26-logistic-example.png differ diff --git a/source/_images/2018-08-26-logistic-regression.png b/source/_images/2018-08-26-logistic-regression.png new file mode 100644 index 00000000..a30fe55c Binary files /dev/null and b/source/_images/2018-08-26-logistic-regression.png differ diff --git a/source/_images/2018-08-26-sigmoid-function.png b/source/_images/2018-08-26-sigmoid-function.png new file mode 100644 index 00000000..00b43a24 Binary files /dev/null and b/source/_images/2018-08-26-sigmoid-function.png differ diff --git a/source/_images/2018-10-10-blocking-synchrnous.png b/source/_images/2018-10-10-blocking-synchrnous.png new file mode 100644 index 00000000..9199839c Binary files /dev/null and b/source/_images/2018-10-10-blocking-synchrnous.png differ diff --git a/source/_images/2018-6-12-mac-theme-appearance.png b/source/_images/2018-6-12-mac-theme-appearance.png new file mode 100644 index 00000000..e9d51053 Binary files /dev/null and b/source/_images/2018-6-12-mac-theme-appearance.png differ diff --git a/source/_images/2018-6-12-mac-theme-profiles.png b/source/_images/2018-6-12-mac-theme-profiles.png new file mode 100644 index 00000000..818d336f Binary files /dev/null and b/source/_images/2018-6-12-mac-theme-profiles.png differ diff --git a/source/_images/clion/deployment1.png b/source/_images/clion/deployment1.png new file mode 100644 index 00000000..3fd466a0 Binary files /dev/null and b/source/_images/clion/deployment1.png differ diff --git a/source/_images/clion/deployment2.png b/source/_images/clion/deployment2.png new file mode 100644 index 00000000..c34599a4 Binary files /dev/null and b/source/_images/clion/deployment2.png differ diff --git a/source/_images/clion/deployment3.png b/source/_images/clion/deployment3.png new file mode 100644 index 00000000..0afb7f10 Binary files /dev/null and b/source/_images/clion/deployment3.png differ diff --git a/source/_images/clion/deployment4.png b/source/_images/clion/deployment4.png new file mode 100644 index 00000000..da70bdcd Binary files /dev/null and b/source/_images/clion/deployment4.png differ diff --git a/source/_images/clion/deployment5.png b/source/_images/clion/deployment5.png new file mode 100644 index 00000000..eb7fe59f Binary files /dev/null and b/source/_images/clion/deployment5.png differ diff --git a/source/_images/clion/remotedebug1.png b/source/_images/clion/remotedebug1.png new file mode 100644 index 00000000..f77cd486 Binary files /dev/null and b/source/_images/clion/remotedebug1.png differ diff --git a/source/_images/clion/remotedebug2.png b/source/_images/clion/remotedebug2.png new file mode 100644 index 00000000..f298ff78 Binary files /dev/null and b/source/_images/clion/remotedebug2.png differ diff --git a/source/_images/clion/remotedebug3.png b/source/_images/clion/remotedebug3.png new file mode 100644 index 00000000..e49a7285 Binary files /dev/null and b/source/_images/clion/remotedebug3.png differ diff --git a/source/_images/clion/remotedebug4.png b/source/_images/clion/remotedebug4.png new file mode 100644 index 00000000..2efcba52 Binary files /dev/null and b/source/_images/clion/remotedebug4.png differ diff --git a/source/_images/ssh_0904.gif b/source/_images/ssh_0904.gif new file mode 100644 index 00000000..ebc47044 Binary files /dev/null and b/source/_images/ssh_0904.gif differ diff --git a/source/_images/ssh_0905.gif b/source/_images/ssh_0905.gif new file mode 100644 index 00000000..e0d57421 Binary files /dev/null and b/source/_images/ssh_0905.gif differ diff --git a/source/_posts/about-this-blog.md b/source/_posts/about-this-blog.md new file mode 100644 index 00000000..76cbbed8 --- /dev/null +++ b/source/_posts/about-this-blog.md @@ -0,0 +1,37 @@ +--- +title: "关于这个博客" +year: 2018 +month: 05 +day: 31 +date: 2018-04-17 +--- + +## 2018年05月31日 +在业务团队里做算法,和一般的算法团队不一样,业务团队里是要解决问题,他不是看你用的算法多高级,你用的公式多牛逼,这其实也不是我擅长的。在业务团队里做算法是很难的,因为他迭代的 + + +## 2018年05月09日 + +最近一直比较焦虑,因为觉得自己做的很多事情没有价值。对于前端、客户端或者后台,有工作量在哪里,至少有苦劳,至少有东西产出,先不说做出来的东西能产生多大的价值,至少在团队中,在这个过程中你有存在的价值和意义。那么算法的同学呢?所谓的算法最后产出的价值有多少?比如所谓的推荐,所谓的千人千面对淘宝天猫的GMV的提升有多少?以前我以为之所以觉得没有价值,是因为在小公司做的东西太low没有价值。现在想法慢慢发生了变化,我觉得我需要面对一个现实,那就是,做技术,很难作出有价值的东西。中国的环境和发展与美国不一样。美国常常是通过技术的革新来维持其竞争力,而在中国,产生巨大影响的无一例外都是产品做得好的。而产品做得好,产品经理还有运营很重要,这分别对应了国内的腾讯和阿里。当然,真正牛逼的都是少数,至少大部分的产品都不怎么样。 + +我这个人总是无法认清现实,总是要挣扎着坚持。好像一定要做什么高大上的东西才对得起自己。总是觉得自己到现在这个位置不容易,如果放弃就会失去很多的东西,想再回头就没有那么容易了。这大概会一直这么禁锢着我,然后无法自拔。 + +算法的价值到底是什么?见了很多的项目,有做算法的,有做算法很厉害的企业的,不管是谁都在不断磨灭我对于所谓的算法工程师的幻想,我不得不接受现实,不是因为我在的位置,不是因为我在的公司,所以我觉得没有意义。而是他本身意义就不大。从某个时间阶段来看,图像算法、自然语言处理等等都对人类社会,对人的生活产生了很重要的影响,但是这些贡献都是极少数人作出的,是那些专门搞算法研究的人做出来的。而我,不是那种人。 + +我的能力有限,我能做的不多。可能就只能是对算法进行一些应用,但是,这不就是我想走的路吗? + +## 2018年04月17日 + +以前断断续续在其他地方也写过很多的博客,然而,总是只有几分的热度,然后就没有心思维护了。一是嫌麻烦,很多东西也没有记下来。二是那些平台总归没有那么自由,审美上也是一只没能让我满意,而且对markdown的支持也是比较牵强。 + +现在平时也会注意积累,但是总不够系统,也没有把心思花下去,收获也是微乎其微。 + +现在是时候改变了。不能同一个问题一而再再而三的Google了,刚跳的坑就忘了。 + +我希望自己不是为了写而写,而是真的有思考才沉淀,每一篇文章都要花精力去写,要写好。既然思考就要好好思考,同时也是真的能给别人带来价值。 + +我的性格有很多的缺陷,很多事情没有坚持下来,我要做的是不断克服我这些缺陷,要克服这些缺陷就要从小事做起,从每一件事情做起。 + +其中一个缺陷就是我太急,总是想快点把事情做完,即使做的不好。然后就是想一件一件事情从我的list里面剔除。没有总结没有思考没有收获。 + + diff --git a/source/_posts/autossh-nat-ddns.md b/source/_posts/autossh-nat-ddns.md new file mode 100644 index 00000000..1e3a17c8 --- /dev/null +++ b/source/_posts/autossh-nat-ddns.md @@ -0,0 +1,187 @@ +--- +title: "SSH端口转发及内网穿透总结" +date: 2018-04-18 +--- + +## 0x00 前言 + +IPV4下,公网IP是奢侈的资源,就算是家里的宽带也不一定能有公网IP,为了能够远程连接家里的Ubuntu,就需要进行内网穿透。 + +已有的方案包括很多,其中TeamViewer、VNC还能做到可视化界面,但是平时的开发并不需要这么重,界面传输反而会加重网络的负担。ngrok、花生壳也可以实现,但是前者很麻烦,后者收费。 + +用SSH实现就非常的优雅,并且可以进行很多的扩展。 + +## 0x01 什么是SSH +SSH表示的是一种网络协议,它定义了一种通过网络建立安全通信的方法,SSH协议从1995年提出以来,演化出了两个大版本,分别是SSH-1和SSH-2.两个版本并不兼容,SSH-2相比于SSH-1安全性更高,并且增加了一些特性。 + +SSH采用的是client/server模型,通过在client和server之间建立加密通道,从认证、加密和数据的完整性三个方面保障通信安全。 + +> SSH协议及基于其开发的产品在名称上很容易混淆,先进行简单的说明。 +SSH-1/SSH-2 表示的是协议。 +SSH1/SSH2表示的是基于SSH1和SSH2协议开发的产品 +ssh/ssh1/ssh2等表示的是客户端程序 +OpenSSH是OpenBSD项目的一个产品,它实现了SSH-1和SSH-2协议。 + +## 0x02 SSH的端口转发 +平时我们用的最多的就是通过SSH实现远程登陆,以及通过scp传输文件。 + +通过SSH协议我们可以在两个计算机之间建立一个安全通道,并且这个通道是双向的。基于这个通道可以实现端口的转发。也就是将这个通道给其他的应用使用,而不仅仅是SSH。 + +

SSH通道建立 + +### 本地端口转发 +假设,我有个服务运行在远程服务器上,如上图中的Host B,这个服务会监听远程服务器的143端口,当有消息过来的时候进行处理。 + +在本地有个应用程序的客户端,它可以通过TCP/IP与远程服务进行通信。现在我希望本地的客户端程序通过SSH隧道进行通信。 + +就可以使用以下的命令: +``` +ssh -L ::: +``` +`-L`表示"local forwarding",`localhost`表示本机地址,`localport`表示本地端口,`remotehost`表示远程服务主机地址,`remoteport`表示远程服务的监听端口,也就是说把所有发送到本地的端口的数据都转发到远程服务器的端口上。然后在本地的应用程序上配置代理到本地端口。 + +

SSH通道建立 + +但是,实际的使用中,我们省略了`localhost`,并且用`localhost`代替`remotehost`,这是为什么呢? +``` +ssh -L :localhost: +``` + +第一个`localhost`保留和去掉的含义不太一样,如果保留`localhost`,表示只能本地的用户链接到这个端口,通过这个端口转发数据,如果你想通过Host C然后把数据通过Host A转发到Host B,这是不允许的。但是可以通过配置中的`GatewayPorts`来改变默认值,或者在命令中加`-g`。或者直接去掉,或者额用"*"代替。 + +为了回答第二个问题,需要先问:`remotehost`和`SSH hostname`一定要同一台机器吗?其实不用。`remotehost`和`remoteport`只要是`SSH hostname`可以访问的机器和端口就可以。 + +其实整个的端口转发过程分成两部分,一部分是在客户端这边,将发往本地端口的数据都通过SSH隧道发送到SSH server上。然后server上再把数据发送到`remotehost:remoteport`上。也就是说前半部分是SSH的客户端的参数,后半部分是SSH服务端的参数 + +整个的端口转发过程变成了SSH客户端和SSH服务端的数据接力。 + +### 远程端口转发 +首先需要注意的是,不管是远程端口转发还是本地端口转发,都是在本地机器上进行的操作,也就是都是在Host A上输入的命令。远程端口转发顾名思义就是对远程的机器上的端口数据转发到本地来 + +远程端口转发和本地端口转发的数据转发方向刚好是相反的,远程端口转发我们希望的是把所有发到远程主机端口上的数据转发到本机来。 + +命令参数的解析也就相反了。 +``` +ssh -R ::: +``` +`-R`表示"remote forwarding",其余的参数含义和本地端口转发一致,但是参数的方向不同,前半部分是给SSH服务端解析的,后半部分是SSH客户端解析的。 + +同样也能进行简化 +``` +ssh -R :localhost: +``` + +> (1)SSH只能对基于TCP/IP协议的应用进行端口转发,并不支持UDP等;(2) + + +## 0x03 内网穿透隧道建立 + +通过ssh实现内网穿透需要有一台有外网ip的主机,因此整个过程实际上有三个对象: + + +| 机器代号 | 机器位置 | 用户 | ip地址 | +| :-----:|:------:|:------:|:-----:| +| A | 内网 | user.a | 192.168.1.155 | +| B | 外网 | user.b | 30.23.1.23 | +| C | 内网 | user.c | 192.168.1.22| + +> 注意,A和C虽然都在内网,但是是不同的内网。 + +首先内网的机器是可以ssh到外网的服务器上的,那么我就希望这个通道能够一直保持,并且我能通过这个通道从外网ssh到内网来。 + +在内网机器A上与外网机器B建立一个远程端口转发通道,当我在机器C上企图对转发端口建立SSH链接时,就会将数据转发到机器A上,这样就实现了内网穿透。 + +通过一下命令就能实现上述的功能。 + +``` bash +$ ssh -fNR 1234:localhost:22 user.b@30.23.1.23 +``` + +`-N`表示不需要执行远程命令; +`-f`表示建立通道后ssh到后台运行 + + +此时就能建立了一个内网上的机器和外网的机器的一个反向隧道(实际上就是一个从外网机器到内网机器的正向隧道)。 +> 注意,这里的`NR`的位置是不能错的,一定要`R`在后面,因为后面跟的是`R`的参数值。 + +此时,你就能够在B机器上通过`1234`端口ssh到A机器上了。但是要注意以下命令中的用户名: + +``` bash +$ ssh -p1234 user.a@30.23.1.23 +``` + +## 0x04 内网穿透隧道的维护 +ssh的连接是会超时关闭的,一旦连接关闭,所谓的隧道也就不存在了,因此需要一个工具,能够在ssh连接断开的时候自动重连。 + +autossh就是这样一个工具。 + +所以首先需要知道ssh连接断开没有,可以通过监听某个端口来判断,一旦发现连接断开了,就重连ssh。autossh会通过发送测试数据,然后根据返回情况来判断连接情况。 + +在autossh中就可以通过以下命令建立维护内网穿透隧道了。 + +``` bash +$ autossh -M2345 -NR 1234:localhost:22 user.b@30.23.1.23 +``` + +在autossh中,`-M`参数就是用来指定监听端口的。 + +我们只是指定了一个`port`端口,实际上`port+1`也被征用了,一个用来发送测试数据,一个用来接收。 + +当`port`设置为`0`时,表示关闭监控功能,这种情况下,只有当ssh退出的时候才会进行重启。最新版的OpenSSH多了一些参数,可以通过增加`ServerAliveInterval`和`ServerAliveCountMax`,确保当ssh发现没有和服务端连接的时候进行重连。 + +autossh中也有个`-f`的参数,加了这个参数就不让你输入密码了,然后就连不上了。然后查看进程的时候就总是有它,想要在这个端口重新进行连接就没用了,死活连不上。普通的kill还没办法kill掉。通过`kill -9 PIDNumber`可以关闭它。所以如果你是通过密码进行autossh连接的时候,不要加`-f`参数。 + + +或者可以通过帮助文档中推荐的方式: + +``` bash +$ autossh -M0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -NR 1234:localhost:22 user.b@30.23.1.23 +``` + +然后同理 + +``` bash +$ ssh -p1234 user.a@30.23.1.23 +``` + +可以借助于这个外网的机器作为跳板机,实现内网穿透。 + +不过注意,少了`-f`的参数,是没办法在后台运行的,后台直接运行的前提是已经配置过ssh的密钥了。 + +## 0x05 服务器重启怎么办? + +首先,要应付服务器重启的情况,那肯定是不能通过输入密码的方式,这里就要用到ssh连接中的通过ssh key实现无密连接了。这个过程其他教程也写了。 + + +``` bash +$ ssh-keygen +``` + +提示输入`passphrase`的时候,直接回车,不然还是要输入密码。这个命令会生成一个私钥一个公钥。为了防止文件被覆盖,可以通过参数`-f`进行重命名密钥文件。不过记得提供完整的路径,不然会生成在当前目录下。 + + +``` bash +$ ssh-copy-id -i /path/to/ssh-key.pub user.b@30.23.1.23 +``` + +上面的命令可以吧选定的公钥文件拷贝到远程主机上,此时,就不需要输入密码就能ssh登陆远程主机了。 + +ssh通过密钥进行登录是有默认文件的,默认情况下会通过`/home/user/.ssh/id_rsa`的私钥与远程中的进行匹配,匹配正确就不需要密码了。如果你是自定义的文件名,需要指定秘钥的路径进行免密登陆。 + +``` bash +$ ssh user.b@30.23.1.23 -i /path/to/ssh-key +``` + +然后可以配置脚本开机自启动。 + + +## ox06 其余参考链接 +[1] https://www.digitalocean.com/community/tutorials/how-to-install-and-manage-supervisor-on-ubuntu-and-debian-vps +[2] [使用SSH反向隧道进行内网穿透](http://arondight.me/2016/02/17/%E4%BD%BF%E7%94%A8SSH%E5%8F%8D%E5%90%91%E9%9A%A7%E9%81%93%E8%BF%9B%E8%A1%8C%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F/) +[3] [SSH反向连接及Autossh](https://www.cnblogs.com/eshizhan/archive/2012/07/16/2592902.html) +[4] [利用ssh反向代理以及autossh实现从外网连接内网服务器](https://www.cnblogs.com/kwongtai/p/6903420.html) +[5] [使用 autossh 建立反向 SSH 隧道管理个人计算机](https://blog.windrunner.me/sa/reverse-ssh.html) +[6] https://docstore.mik.ua/orelly/networking_2ndEd/ssh/ch09_02.htm +[7] https://www.ibm.com/developerworks/cn/linux/l-cn-sshforward/index.html +[8] https://unix.stackexchange.com/questions/236865/what-does-bind-address-mean-in-ssh-port-forwarding/236867 + diff --git a/source/_posts/blocking-nonblocking-async-sync.md b/source/_posts/blocking-nonblocking-async-sync.md new file mode 100644 index 00000000..fc43277a --- /dev/null +++ b/source/_posts/blocking-nonblocking-async-sync.md @@ -0,0 +1,54 @@ +--- +title: "同步与异步、阻塞与非阻塞" +date: 2018-10-10 +--- + +## 0x00 引入问题 + +看《深入分析Java Web技术内幕》的时候,看到的同步与异步,阻塞与非阻塞的概念,这个问题之前在群里也有人说过,但是当时印象不深刻,也没有在意,现在在学后端的开发,还是需要把这些概念捋清楚。 + +先来看看书里面是怎么说的。用我自己的话进行了转述。 + +对于同步(synchronous)和异步(asynchronous): +> 同步就是一个任务的完成需要依赖另一个任务,当被依赖的任务完成以后,依赖的任务才能完成,异步就是依赖的任务通知被依赖的任务去完成工作,不需要被依赖的任务完成,依赖的任务继续进行。从任务完成的角度看,同步就是需要两个任务都完成才算完成,异步是只要依赖的完成,那就是完成了。 + +对于阻塞(blocking)和非阻塞(non-blocking): +> 阻塞和非阻塞的概念是针对CPU而言的,阻塞就是CPU停下来等待慢的任务完成,然后再去干其他的事情,而非阻塞就是慢的操作在执行时,CPU去做其他的事情。 + +## 0x01 现有的讨论 + +网上有一些不同的意见。 + +讨论1:在[stackoverflow](https://stackoverflow.com/questions/2625493/asynchronous-vs-non-blocking)上面,得票最多的人说:大部分情况下,同步与阻塞,异步与非阻塞其实说的都是一件事情,只有在某些语境下才有差异。比如举了`socket` API的例子,在`socket`中,1.阻塞与同步是一个意思,会一直挂着线程直到有返回值;2.非阻塞的意思是,如果调用的API还没有准备好(比如数据没有就绪等),那么就会返回错误,然后结束。需要等到就绪以后再调用API;2.异步的意思是,调用API以后,API所进行的操作就会到后台去运行,等有了结果再通过回调函数或者事件返回结果。 + +对`socket` API不是很了解,感觉也是说的很模糊,表述也有点问题,并不值得这么多赞。 + +讨论2:这是来源于一篇[博客](http://www.programmr.com/blogs/difference-between-asynchronous-and-non-blocking),首先同步的概率有个很好的例子诠释:HTTP,它就是一个同步的协议,浏览器发送一个request,然后就会一直等着这个response,这个response不来,下一个request就不会发送出去,注意,这里说的是request的同步,也就是说每一个request的任务是按序进行的,上一个request结束才会进行下一个request。阻塞的概念可以看Java中的`InputStream.read()`方法(用来读取文件),调用这个方法以后,它会一直等到读取的数据有效(比如读到了结束符或者抛出异常)才会返回。这就是一个阻塞的过程。 + +同步调用通常需要一个回调或者事件,用来触发响应已经有效的信号。而对于非阻塞,它会立刻返回一个结果不管是不是有效,可能需要反复调用多次才能拿到有效数据,非阻塞一般说的就是IO,异步一般说的是更加广泛的操作。 + + +## ox02 我的一些想法 + +我们先从阻塞和非阻塞入手,定义很明确,那就是是不是占着CPU不拉屎。现代的CPU,可以运行多任务,其实就是把任务的执行过程分成很多的细粒度,然后在任务的细粒度之间来回切换,其实每一时刻只进行一个任务,但是给你的错觉就是同时进行了很多的任务。因此阻塞不阻塞就是看当任务**不使用**CPU的时候,是不是让它释放出来。注意加粗的关键字,它另一层的意思就是,有些任务是不使用CPU的,比如说IO,这个[问题](https://stackoverflow.com/questions/13596997/why-is-the-cpu-not-needed-to-service-i-o-requests)下面有个回答提到,他说**硬盘有自己的专属芯片,用来出来CPU交代的任务,比如说读写等。** + +所以我们常说的就是IO阻塞或者IO非阻塞,相对来说阻塞的概念比较狭隘,也比较底层。 + +而同步与异步其实是更宏观的角度去看待问题,从任务的角度去看,而且一般来说不是指底层原子任务。 + +同步IO或者阻塞IO都有这种说法,也都会对IO的性能产生影响,但是是不同的维度。从书中的例子我们也能看出来。 + +

+

+ +同步阻塞和同步非阻塞,说的就是到了IO操作这步以后,是不是要等着IO操作结果的返回。但是,**同步非阻塞增加CPU的消耗**,这点不是很懂,为什么会增加CPU的消耗? + +当到了异步与同步的区别,就变得更宏观了,也就是说出现了几个任务,需要往分布式数据库中的多个数据库中写入同一条数据,向一个数据库中写数据就是一个任务,写到多个数据库中就是多个任务,多个任务并行就是异步。而每一个任务操作IO的时候都是阻塞进行。 + +异步非阻塞进行了扩展,原来异步阻塞中每次任务是写入一份数据,现在每一个任务要传输多份数据,IO也变成了网路IO。同时数据的传输量虽然不大,但是比较频繁,因此,在每个任务异步的同时,每一个机器的每一份数据也都是非阻塞,第一条数据发出去赶紧继续发第二条。 + +Anyway,你也可以说咬文嚼字,但是这么说下来,确实感觉更合理,也更清晰了。 + +以上。 + + diff --git a/source/_posts/clion-c__-coding.md b/source/_posts/clion-c__-coding.md new file mode 100644 index 00000000..6218e5a9 --- /dev/null +++ b/source/_posts/clion-c__-coding.md @@ -0,0 +1,97 @@ +--- +title: "Clion远程Debug" +date: 2018-06-13 +--- + +## 0x00 +在Mac上如何优雅的写C++代码一直困扰着我,起初有了Visual Studio Code,但是代码自动补全的能力真的是太弱了,导致有一段时间一写C++的代码就要带上Windows的电脑,非常的麻烦。不仅仅是Mac,在Linux平台下也是,没有了Visual Studio的支持,我就完全没法写C++代码了,让我非常痛苦。终于,Clion救世主出现了,跨平台,基于CMakelist.txt编译,颜值又高,功能齐全! + +它的功能就不多说了,可以到官网去学习。这次主要说一下远程调试的问题,总结一下。初学者可以先看官网上关于[远程调试](https://www.jetbrains.com/help/clion/run-debug-configuration-remote-gdb.html)的部分。 + +## 0x01 +首先第一步是要同步代码,把本地的代码和远程的代码同步一下,不然修改代码就会变得很麻烦。 + +

配置代码同步 +

+ +选择`SFTP`,这样的话可以通过`SSH`进行文件的同步。 +

配置代码同步 +

+ +

配置代码同步 +

+ +把本地需要同步的路径和远程主机的路径关联上。 + +

配置代码同步 +

+ +配置好各个路径以后直接把本地的代码上传上去,还能设置自动上传代码。登陆远程服务器,就可以看到代码了。 + +

配置代码同步 +

+ +然后就能随心所欲上传下载更新文件了,调试利器。 + +## 0x02 +现在可以进行代码调试了。 + +先说说远程debug的基本原理。其实就是首先在远程端运行程序,运行了就马上暂停,同时监听配置的端口,然后本地开始运行,运行就会发消息给远程服务器,两个端口一对上就开始debug了。 + +首先,我们要让远程的代码先跑起来,先在远程端对代码进行编译,在编译的时候一定要注意,如果你要进行debug,必须加上参数`-DCMAKE_BUILD_TYPE=Debug`,否则你在Clion上怎么打断点也没用。 + +另外为了能够远程debug,需要在远程服务器上安装**gdbserver**,直接`apt-get install`一下。另外需要注意的是,远程主机上的`GDB`版本要和本地的版本一致,否则会出问题。 + + +编译好以后我们回到本地,对本地进行一些配置。 + +

远程调试 +

+ +

远程调试 +

+ +

远程调试 +

+ + +看上面的几个参数,看看都是怎么来的。 + +首先是`GDB`,这个必须是编译出来的基于Linux平台的才可以,而不是基于Mac平台的。具体的教程参考[这里](https://blog.jetbrains.com/clion/2016/07/clion-2016-2-eap-remote-gdb-debug/),编译好了选择相应的程序就可以了。 + +这个`target remote args`比较好理解,按照这个格式写,最后的端口是自定义的,与后面的远程端的匹配就可以了。 + +`Symbol file`其实是在远程端生成的程序,同步下来,选中。 + +`Sysroot`是本地的源代码的路径,这个填不填都能debug,但是我发现没有加这个话调试起来非常慢。 + +`Path Mappings`顾名思义就是把远程的和本地的路径进行关联。这步是必须做的,否则断点打了也没用。 + +现在这样的配置就完成了。可以开始debug了。 + +在远程端运行 +``` bash +gdbserver localhost:7000 ./remoteTest +``` +此时,远程端的程序就会监听7000端口,同时会一直等待。此时在本机启动调试。 + +

远程调试 +

+ +## 0x03 one more thing + +如果是在同一个局域网中的机器,毫无疑问,是一点问题都没有的,如果远程主机有外网ip也是可以的。 + +但是,如果没有外网ip,又不在同一个局域网怎么办呢? + +这里就到了`SSH`发挥作用的时候了。 + +如果要对这种主机进行debug,首先需要能够连接`ssh`,按照之前的教程先建立这个隧道。然后在远程主机和外网服务器之间建立一个远程端口转发。相当于把外网主机的7000端口的请求转发到远程服务器的7000端口上,完美实现调试! + +`ssh -NR 7000:localhost:7000 root@10.12.1.3` + +然后就是按照前面的步骤进行debug就可以了。 + + + + diff --git a/source/_posts/deep-learning-models-and-applications.md b/source/_posts/deep-learning-models-and-applications.md new file mode 100644 index 00000000..923796af --- /dev/null +++ b/source/_posts/deep-learning-models-and-applications.md @@ -0,0 +1,149 @@ +--- +title: 《深度学习模型及应用详解》读书笔记 +date: 2019-12-01 +mathjax: true +--- + +## 概述 +难度还是有点大,不适合入门的,有些章节现在还是有很多看不懂,特别是第8,10,11,12章,后面有机会再继续看吧。 + +## TODO +1. 什么是`nce_loss`,它`sampled_softmax_loss`之间的区别。 +2. dropout的起源和使用。 +3. Batch Normalization具体的计算和推导 +4. 《Query-drive Iterated Neighborhood Graph Search for Large Scale Indexing》论文研究一下 +5. Rich-CDSSM、《Learning Deep Structured Semantic Models for Web Search using Clickthrough》 +6. RapidScorer算法到底是个什么流程,有什么应用。 + +## 第二章 深度学习开源框架 +深度学习的变化真的很快,在2015年的时候,tensoflow刚出来,theano还是深度学习框架的霸主,而如今,theano都已经销声匿迹,只剩下了tensorflow和pytorch在争霸了。 + +深度学习的框架中,主要有两种分布式架构,分别是**Parameter Server-Workers**和**All-Reduce**。 + +Parameter Server-Workers有两部分,分别是Parameter Server和Wokers,前者是用来存储和处理参数的,后者是用来负责处理数据的,如果是多个Parameter Server和Woker的话,就分别只负责一部分。Parameter Server从Work中获取数据计算后的梯度信息,然后更新参数,Work在处理的时候会从Parameter Server上获取参数数据进行数据处理,得到当前的数据梯度信息。 + +All-Reduce的模式是每台机器既负责计算,也负责模型参数的更新。把数据分成n份,分别在每台机器上计算,然后求一个平均的梯度,然后把所有机器上的梯度都按照这个参数进行更新。 + +## 第三章 多层感知机在自然语言处理方面的应用 +自然语言处理中最简单的任务就是计算两个句子或者两篇文档之间的相似度。 + +要解决这个问题,首先要把词和文本在数学上表示出来。可以通过**bag-of-words**进行建模。假设一篇文档中有100不同的词,那么我可以用一个1000维的向量来表示某一个词,这个词出现的索引置为1,其余地方置为0,所有的单词就都能用1000维的向量唯一表示出来了。那么一篇文档的向量就可以通过把这篇文档中的每一个词向量相加得到,也就是如果这篇文章中出现了这个词,那么对应的索引上就置为1,没有出现就是0。 + +但是如果只是看有没有出现,还是有点粗糙,于是发明了**TF-IDF**算法。向量中不仅表示文档中是否出现了该词,更是表示该词在文档中的重要程度。对于任意一个词,以这个词在当前文档出现的次数为分子,以这个词在所有的文档中出现的次数的`$log$`值为分母,分子处以分母的值就是这个词的权重。这个也很好理解,但是很妙,如果某个词只在当前文档出现,说明这个词比较与众不同,能够反应这个文档和其他文档的差别。像“的”这种单词在什么文档中都能出现,它的价值就很小,信息量很少。 + +上面的做法有个缺点就是**无法反应语义**,比如“称赞”和“夸奖”其实表达的是一个意思,但是在词向量中就是完全不同了。 + +因此后来发展出了**Word2Vec**算法。 + +目前最常见的Word2Vec算法有两种,分别是CBOW(Continuous Bag-of-Words)算法和Skip-Gram算法。他们的本质是一样的,而且互为镜像。 + +对于一个单独的字来说是没有语义的,语义是体现在上下文中的,什么词跟在什么词后面是具有一定模式的,这种模式也产出了语义。我们可以通过一个上下文窗口,把当前的词和其前后的一个或多个词进行关联,构建出正样本数据及其标注。负样本进行抽样学习。 + +CBOW算法就是以上下文为输入,当前单词为输出,通过上下文预测当前词,而Skip-Gram算法是以当前单词为输入,上下文为输出,通过当前单词预测其上下文。 + +把当前单词转化为上下文就需要一个编码映射,这个就是我们要学习的模型。可以通过前面的简单的方法把单词映射为特征向量。 + +但是Word2Vec有一些缺陷,比如:1.固定短语没法识别,比如"Best Buy"其实是一家电商,但是如果放到上下文就不能理解了,可以先识别短语,然后把短语当成一个整体。2.有些词词性完全不同,但是它的上下文一样,比如"It was a bad weather yesterday"和"It was a good weather yesterday"。3.一词多义的问题很难解决。4.当词在语料中出现的次数很少时就不能很好的学习到高维信息了,有些人提出了基于词根的建模,一定程度上可以缓解这个问题。 + +由于负样本的数量特别多,所以有一种方法是负样本取样,我之前一直理解的就是我直接选取一个正样本,然后选取几个负样本,然后把正样本和负样本合在一起计算softmax不就可以了嘛?但是好像这种做法有问题。照理说应该随机采样。书中参考论文《Distributed Representations of Words and Phrases and their Compositionality》得到了采用采样的方法计算的loss,但是原文我也没看出有这个公式的推导。 + +$$ +J_k(\theta) = \log(1 + \exp^{(-z^1)}) + \sum_n\log(1 + \exp^{z^{i_n}}) +$$ + +其中`$i_n \in \{0,1,...,9\},i_n \ne 1$`,`$i_n=1$`是我们的正样本。 + +虽然论文中没有推公式,但是我们理解起来没有那么困难。其实就是让正样本的`$\exp^{(-z^1)}$`越大,那么loss越小,而负样本的`$\exp^{z^{i_n}}$`值越大,那么造成loss越大,这样让正样本的概率越来越大。 + +[示例代码](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/tutorials/word2vec/word2vec_basic.py#L205)中提到,这里用了`tf.nn.nce_loss`而没有用`tf.nn.sampled_softmax_loss`,这块还没有仔细看。 + + +## 第四章 卷积神经网络在图像分类中的应用 +文中提到,引入ReLU激活函数后,可以减少梯度消失的影响,但是会带来另一个问题,有可能存在很少被激活的“死节点”。这个原因应该是小于0的部分梯度直接变成0造成的,但是,说明这部分的参数就是没用的啊,不可能参数都利用起来吧,就算是用sigmoid或者tanh激活函数,应该也会存在这种问题,只不过那种表现是梯度很小。 + +局部响应归一化(Batch Normalization)和仿生学中临近的非常活跃的神经元之间存在竞争机制,其实Normalization的操作很多地方都有,只不过这里是在特征图之间进行。 + +dropout最开始提出来是为了能够融合多个模型?这个没有看过具体的论文不太清楚。那么dropout应该用在哪一层呢?最后?还是可以用在中间。 + + +## 第五章 递归神经网络 +LSTM算法在2003年就已经在语音识别领域大有作为了,但是深度学习在2010年以后才真正普及,这是什么道理? + +RNN和普通的深度学习网络不一样的地方就在于它有“记忆”的功能,对于普通的神经网络而言,不同的输入之间是无关的,其他的输入信息不会作用到另一个输入中,而RNN就把这个关系加上了。不同的输入其参数是共享的,并不是不同的模型,这个思维有点像在《python深度学习》里面提到的,把句子正向反向都输入到网络中进行处理,因为处理句子的模型参数应该是一套而不是两套,所以正向句子和反向句子输入的是一个模型,然后在后面把这两个输出连接到一起,这个也是同理,所有的语音应该是用同一套模型参数去处理,只不过RNN可以把之前的信息也加进来。 + +双向递归神经网络(Bidirectional Recurrent Neural Network, BRNN)和长短期记忆模型(Long Short-Term Memory, LSTM)是RNN的两种变种。 + +BRNN是一个信息可以是正向传入,也可以反向传入,这和上上段的思维是一样的。 + +LSTM是解决普通的RNN不能有效建模长距离依存关系的问题。下面一张图可以说是非常清晰的解释了什么是LSTM,比书上讲的那么多门清晰的多的多了。 + +

LSTM + +## 第六章 DeepIntent模型在信息检索领域的应用 +普通的RNN可以接收一系列的输入,最后输出一个结果,当然中间也有结果输出,只是在最后的时候这部分很难用上,有时候我们要叠加LSTM模块,前一个模块的所有输出都引入到后一个模块上。还有另一种做法就是引入**注意力机制**,把中间的所有输出也都加上,然后通过一个权重向量得到一个输出。 + +我们在表达的时候其实是有重点的,有些词语很重要,有些词语去了也没有关系,词语的重要程度是不同的,因此引入注意力机制。 + +注意力机制的整个流程我们可以总结为下。 + +我们先假设一种场景,用户输入一个句子`$X=\{ x_1, x_2,...,x_t \}$`,然后我们要根据用户的输入要给他推荐广告。其中`$x_t \in \mathbb{R}^V$`,这里的`$V$`表示的是向量的纬度,表示词典中不同词的个数,然后通过one-hot方法把原始输入映射成特征向量。 + +有了特征向量之后,我们先进行一层特征提取,通过embedding层对原始特征向量进行变换。 + +$$ +e_t = W_{emb}x_t, s.t. W_{emb} \in \mathbb{R}^{d_{emb}\times V} +$$ + +其中的`$d_{emb}$`就是生成的嵌入式向量的大小。 + +经过嵌入式层的操作以后,就生成了`$\{e_1, e_2, ... , e_t\}$`的特征向量。 + +通过简单的RNN的网络,我们可以有以下操作。 + +$$ +h_t = H(e_t, h_{t-1}) +$$ + +其中的`$H$`就是RNN的映射权重,他是一个非线性的映射。可以有多种选择。每一个输入都能得到一个输出,到现在就有输出`$\{h_1, h_2, ... ,h_t \}$`. + +所谓的注意力机制就是对于每一个输出都有一个权重,最后得到一个输出. + +$$ +h = \sum_{t=1}^{T}\alpha_th_t, \alpha_t = \frac{\exp^{s(h_t;\theta)}}{\sum_{t=1}^T(\exp^{s(h_t;\theta)})} +$$ + +这个`$\alpha_t$`就是我们的权重,这个权重通过`$s(h_t;\theta)$`得到概率分布,这就是所说的注意力模型网络。整个过程就是如下图所示了。 + +

RNN + +**在经过注意力模型`$s(h_t;\theta)$`后输出了一系列的值,这个值经过上面的公式计算变成权重。但是直接输出的值还经过了一道加工,就是把所有的值都减去了最大值,这样保证所有的值都是小于等于0,如果其中的最大值比较大,按照指数增长的趋势,可能会造成溢出。** + +但是整个流程下来,loss怎么计算其实还不是很清晰。 + +输入用户的输入,就是类似于图像中的像素,是一系列的特征,然后每经过一次RNN的网络,它输出的不是一个数值,而是一个特征向量,通过注意力模型得到的分数是每一个分量的分数,最后经过权重计算后得到的也是一个向量,用这个向量和广告得到的特征向量进行比较,可以得到两个特征向量的相似度。在我们平时的计算中,一个例子进行就有负样本,但是我们这里是要通过输入才有负样本,也就是一个batch输入既有正样本也有负样本,然后把这个看成一体计算loss。 + + +## 第七章 图像识别及在广告搜索方面的应用 + +从特征提取模型中提取出1024维的特征向量,但是这个特征向量还是很长,因此还需要把特征向量进行压缩,压缩的方法可以通过PCA或者Rich-CDSSM算法提取成64维的特征向量。然后通过ANN(近似最邻近)来搜索两个向量之间的相似度。找出和query图像相似的内容。 + +书中也提到了NGS(邻域图搜索,Query-drive Iterated Neighborhood Graph Search for Large Scale Indexing)。这个可以参考一下用于向量的搜索。 + +Rich-CDSSM的算法到底是什么 + +## 第八章 Seq2Seq模型在聊天机器人中的应用 +最重要的部分一点代码也没有,很多问题也根本没有说清楚。 + +## 第九章 word2vec的改进:fastText模型 +word2vec中我们通过单词的n-gram方法构建输入输出对,但是会遇到生僻词、未知词,这个就没办法了。但是英文单词中很多单词是由词根等构成的,我们可以在单词的层面应用n-gram方法,这个就是*subword*了。每一个单词由多个特征向量构成,每一个特征向量就是我们的subword。 + +本章最重要的内容就是**分层softmax**算法,其实我在实际中就遇到过,在求解softmax的值的时候,如果维度太大,会导致计算机内存不够算不下来,这里提出了分层的softmax算法。 + +所谓的分层softmax就是对所有的类构建成树状结构,把softmax的多分类变成sigmoid二分类。 + +## 第十章 生成对抗网络 + + + +## 第十三章 深度学习的下一个浪潮 +我觉得未来的深度学习还是得在强化学习上面,其他方面也肯定大有作为,想想看互联网刚出来的时候不过是应用在很小范围内,但是现在几乎生活的方方面面都是计算机和互联网,未来深度学习或者机器学习会普及到生活的方方面面,显然现在还远远没有达到。 \ No newline at end of file diff --git a/source/_posts/linear-regression.md b/source/_posts/linear-regression.md new file mode 100644 index 00000000..37a90bd8 --- /dev/null +++ b/source/_posts/linear-regression.md @@ -0,0 +1,178 @@ +--- +title: "机器学习实践——线性回归(Linear Regression)" +date: 2018-08-24 +mathjax: true +--- + +## 0x00 回归问题的引入 +有一批数据集,现在希望找出一个公式去拟合这批数据集,至于用几个参数,参数都是几阶,就看具体的数据集了。回归问题更像是解方程,有未知数,有训练集作为方程,几对训练集就有多少个方程,当方程数=未知数个数,有唯一解,当方程数>未知数个数,可能就无解,当方程数<未知数个数,有大于一个解。只不过现实中的数据都没有那么理想,并不能100%得到拟合,**只能是选取参数,尽可能的去拟合已有的数据。** + +## 0x01 线性回归问题概述 +现在我们有一批数据集`$(\overrightarrow{x}^{(i)},y^{(i)}),i\in[1,m]$`,数据总共有`$m$`组,`$\overrightarrow{x}$`表示的是向量,可以是多维的数据`$\overrightarrow{x}=(x_{0},x_{1},...,x_{n})$`,总共有`$n \times 1$`维的特征。 +对于我们来说,特征就是我们的输入,我们希望通过`$\overrightarrow{x}$`的输入得到我们的输出`$y$`。每一个特征都有对应的系数,因此有`$\overrightarrow{\theta}$`,其大小也是`$n \times 1$`。我们要求的就是这个`$\overrightarrow{\theta}$`. + +总的来说,我们就是希望能够得到以下的关系 + +$$ +y^{(i)} = \overrightarrow{\theta}^{T}\overrightarrow{x}^{(i)} +$$ + +方便起见,向量符号统一去掉。 + +现实中肯定是没有那么好的数据的,并不能保证拟合所有的已知点。我们只是**尽可能接近**的去拟合已有的数据。 + +尽可能拟合其实包含了两层的意思。一层是估计值和实际值尽可能的接近,也就是说每一个训练集与预测值的误差的总和尽可能的小。另一层是指尽可能的拟合更多的数据,比如有一组参数可以拟合100个点,另一组参数可以拟合1000个点,我们肯定是选择后者参数。 + +根据上面的两个思路就有了两种解法。 + +## 0x02 误差角度的线性回归分析 + +对于第一层意思,其实就是最小二乘法里面用到的。误差 + +$$ +\varepsilon=|y^{(i)} - \theta^{T}x^{(i)}| +$$ + +将所有的训练数据误差进行累加。 + +$$ +L=\frac{1}{2}\sum_{i}^{m}(y^{(i)} - \theta^{T}x^{(i)})^2. +$$ + + +$$ +\begin{split} +\delta&= +\begin{bmatrix} +y^{1}\\ +y^{2}\\ +\cdots \\ +y^{m} +\end{bmatrix} +- +\begin{bmatrix} +\theta^{T}x^{1}\\ +\theta^{T}x^{2}\\ +\cdots \\ +\theta^{T}x^{m} +\end{bmatrix}\\ +&= +\begin{bmatrix} +y^{1} - \theta^{T}x^{1}\\ +y^{2} - \theta^{T}x^{2}\\ +\cdots \\ +y^{m} - \theta^{T}x^{m} +\end{bmatrix} +=Y - X\theta +\end{split} +$$ + +式子`$(1)$`用矩阵可以表示为 + +$$ +L=\frac{1}{2}\sum_{i}^{m}(y^{(i)} - \theta^{T}x^{(i)})^2 = \frac{1}{2}(Y-X\theta)^{T}(Y-X\theta) +$$ + +为了让误差最小,对`$L$`进行求导,就能得到最值点。 + +$$ +\begin{split} +L(y|x;\theta)&=\frac{1}{2}(Y^{T}-\theta^{T}X^{T})(Y-X\theta)\\ +&=\frac{1}{2}(Y^{T}Y-Y^{T}X\theta-\theta^{T}X^{T}Y+\theta^{T}X^{T}X\theta) +\end{split} +$$ + +$$ +\begin{split} +\frac{\partial}{\theta}L&=\frac{1}{2}(0-Y^{T}X-(X^{T}Y)^{T}+(X^TX\theta)^{T}+\theta^{T}X^{T}X)\\ +&=\frac{1}{2}(-2Y^{T}X+2\theta^{T}X^{T}X) +\end{split} +$$ + +令`$\frac{\partial}{\theta}L=0$`,得到 + +$$ +\theta^{T}X^{T}X=Y^{T}X\Leftrightarrow(X^{T}X\theta)^{T}=Y^{T}X\Leftrightarrow X^TX\theta=X^{T}Y\Leftrightarrow \theta=(X^{T}X)^{-1}X^{T}Y \tag{2} +$$ + +> 上面的推导过程主要的麻烦的地方就是`$\frac{\partial}{\theta}(\theta^TX^TY)$和$\frac{\partial}{\theta}(Y^TX\theta)$`怎么求。简单来说就是当`$\theta$`在前面的时候,求导的时候后面要进行转置,当`$\theta$`在后面的时候,保留前面的参数即可。 + +## 0x03 概率角度的线性回归分析 +我们的预测值和实际值存在出入,我们考虑一个较为合理的假设,假设这个误差是一个正太分布,其概率密度就是属于`$\epsilon \sim (\mu,\sigma^2)$`,其均值假设为0(这个假设也是合理的,比较可以把这部分的值分到截距那块)。因此有 + +$$ +y^{i}=\theta^{T}x^{i}+\epsilon^{i} +$$ + +$$ +p(\epsilon^{i})=p(y^{i}-\theta^{T}x^{i})=p(y^{i}|x^{i};\theta)\tag{3} +$$ + +> 怎么看待`$(3)$`式也是个问题,这里可以这样去理解。有了参数$\theta$,自变量$x$是已知的,不同因变量`$y$`的概率也就知道了,把所有的情况都考虑进去`$y$`的概率分布也就能得到了。 + +$$ +\begin{split} +p(y^{i}|x^{i};\theta)&=\frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{(\epsilon^{i})^2}{2\sigma^2}}\\ +&=\frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{(y^{i}-\theta^{T}x^{i})^2}{2\sigma^2}} +\end{split} +$$ + +于是就有了关于预测值`$\hat{y}$`的概率分布情况。 + +上面我们一直在强调一个观点,那就是,基本上是做不到拟合所有的点的,我们的目标是**拟合尽可能多的点**,比如对于正太分布,`$x=0$`的时候的概率是最高的,那么我们就用这最多的点去拟合我们的方程。所以有了所谓的**最大似然估计**。 + +每个样本都是独立同分布,因此所有的样本的概率分布可以这样计算: + +$$ +P=\prod_{i}^{m}(\frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{(y^{i}-\theta^{T}x^{i})^2}{2\sigma^2}}) +$$ + +因为我们只是找最值,因此两边都取$log$: + +$$ +\begin{split} +L=\ln{P}&=\sum_{i}^{m}(\ln{(\frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{(y^{i}-\theta^{T}x^{i})^2}{2\sigma^2}})})\\ +&=\sum_{i}^{m}(\ln(\frac{1}{\sqrt{2\pi}\sigma})+(-\frac{1}{2\sigma^2}(y^{i}-\theta^{T}x^{i})^2))\\ +&=m\ln(\frac{1}{\sqrt{2\pi}\sigma})+(-\frac{1}{2\sigma^2})\sum_{i}^{m}((y^{i}-\theta^{T}x^{i})^2) +\end{split} +$$ + +为了求最值,和`$\sigma$`是无关的。为了求$L$的最大值,就是求`$\frac{1}{2}\sum_{i}^{m}((y^{i}-\theta^{T}x^{i})^2$`的最小值。于是又回到了式`$(1)$`。接下去的推导就如上所述了。 + +## 0x04 过拟合与正则 +当然,还有过拟合的问题。理论上,越多的参数越是能够拟合训练数据,参数到一定程度的时候,实现0误差也不是不可能,但是,这不是我们想要的,因为他的泛化能力特别差,很多数据是因为噪声造成的,而噪声不是通过训练数据去预测的。因此,我们需要控制参数。 + +## 0x05 Coding Example +以Python为例,测试一下简单的实现。随机生成一系列的自变量`$x^{i}$`,然后取`$y=ax+b,a=1.5, b=4.3$`,得到一系列的`$y$`,加上随机噪声,根据`$(x^{i},y^{i})$`点对计算出参数`$a,b$`。 + +按照式`$(2)$`,可以的到 + +$$ +X= +\begin{bmatrix} +x^{1} & 1 \\ +x^{2} & 1 \\ +\cdots & \cdots \\ +x^{m} & 1 +\end{bmatrix} +$$ + +$$ +Y= +\begin{bmatrix} +y^{1} \\ +y^{2} \\ +\cdots \\ +y^{m} +\end{bmatrix} +$$ + +$$ +\theta= +\begin{bmatrix} +a\\ +b +\end{bmatrix} +$$ + +直接将数据代入到`$(2)$`式中即可计算得到`$\theta$`。 \ No newline at end of file diff --git a/source/_posts/mac-appication-config.md b/source/_posts/mac-appication-config.md new file mode 100644 index 00000000..06dc08a6 --- /dev/null +++ b/source/_posts/mac-appication-config.md @@ -0,0 +1,34 @@ +--- +title: "mac应用配置总结" +date: 2018-06-12 +--- + +## 0x00 前言 +我有一种强迫症,如果IDE丑,就会浑身难受,而如果工具长得好看,写代码的动力都会上来的。最近对mac上常用的工具进行了一些配置,让他们看上去更优雅。写个总结的文章。其实总结起来就是Material Design,基本把我的工具都换成了这种风格。 + +## 0x01 Visual Studio Code +最近沉迷于Material Design的风格,配色很是让我喜欢。因此Visual Studio Code也搞了一套。主题采用的是[Material Palenight Theme](https://marketplace.visualstudio.com/items?itemName=whizkydee.material-palenight-theme),然后把字体改成了`Meslo LG M Regular`,最近也是沉迷于这个字体。具体的配置如下,图标等也换了一下,感觉还不错。 +``` json +"workbench.colorTheme": "Material Theme Palenight", +"editor.fontFamily": "Meslo LG M Regular ,Menlo, Monaco, 'Courier New' monospace", +"editor.fontSize": 14, +"materialTheme.fixIconsRunning": false, +"workbench.iconTheme": "eq-material-theme-icons-palenight" +``` + +## 0x02 Clion IntelliJ +Jetbrains全家桶简直的棒呆。Clion用来写C++的代码也是非常的爽,而且还能够调试远程Linux环境下的代码,一直苦于离开Windows平台不能好好写C++的代码的结终于解了。 + +Clion的主题同样是Material Design,直接在`Plugin`中搜索`Material Design UI`就可以了。然后调整一下字体还有字号,再把一些没有必要的错误警告提示的下划波浪形取消,就差不多了。风格的话选择`Atom One Dark Theme`,虽然说Atom软件做的不怎么样,但是这个设计的IDE风格确实是不错。 + +## 0x03 Iterm2 +首先是基于[这篇文章](https://medium.com/@Clovis_app/configuration-of-a-beautiful-efficient-terminal-and-prompt-on-osx-in-7-minutes-827c29391961)对Iterm2进行改造,可以实现一些很实用的功能,并且看着也不错。 + +主题设置好了,但是标题栏还是很丑,和整个界面不搭。再设置一下这个。 +具体的配置见如下截图。 +![](https://joeltsui.github.io/assets/images/2018-6-12-mac-theme-appearance.png) +![](https://joeltsui.github.io/assets/images/2018-6-12-mac-theme-profiles.png) +上面主要是把标题栏下面的白线去掉,然后启动标题栏的颜色设置。但是想要把标题栏的颜色呵背景颜色设置成一样的发现无法生效。google了才知道,mac High Serria版本已经不能修改标题栏颜色了。但是有人搞出了一些很厉害的东西,不得不佩服,见[这里](https://gitlab.com/gnachman/iterm2/issues/4080),下面有个人分别对标题栏还有背景设置了不一样的颜色,但是最后显示出来就是背景与标题栏融合了。非常厉害。 + + + diff --git a/source/_posts/python-deep-learning.md b/source/_posts/python-deep-learning.md new file mode 100644 index 00000000..7c4a15ce --- /dev/null +++ b/source/_posts/python-deep-learning.md @@ -0,0 +1,198 @@ +--- +title: "《Python深度学习》读书笔记" +date: 2019-11-25 +mathjax: true +--- + +## TODO +1. 深入了解**SeparableConv**、**DepthwiseConv**、**BatchNormalization**的计算公式和操作。 +2. 如何对模型进行集成。找一些kaggle的例子。 +3. word2vec算法是什么 +4. 循环神经网络中使用dropout的原理 +5. `L-BFGS`算法是什么 + +## 第四章 机器学习基础 +现在`dropout`操作用的很多,但是我之前全部都理解错了,在训练的时候加上`dropout`,它会屏蔽一部分的节点,在测试的时候不会屏蔽,但是输出的时候要乘以`dropout`的比率系数。(这个是为什么??测试的就是就是为了检验整个模型的效果啊,也不训练参数,为啥要乘以比率) + +## 第五章 深度学习用于计算机视觉 +本章对我来说收益最大的是卷积神经网络的可视化。主要有三种可视化,1. 是把每一层的激活层的输出可视化,它表示经过神经网络之后,每一层的输出结果是什么。从这个可以看出来,前面的层主要是一些边缘探测器,它几乎保留了原始图像中的所有信息,随着层数的增加,提取的信息越来越抽象,越来越难以直观的理解,还有一种现象就是随着层数增加,越来越多的输出是空白的,也就是这些过滤器没有找到图像中符合的编码信息。2. 是可视化过滤器,我最开始的想法是,过滤器不就是每个卷积网络的kernel这些吗?这些不就是过滤器吗?但是这个有点过于底层,其实我们最想知道的是某一层的整体的过滤效果,而不是单个的,单个的其实很难看出什么东西。所以这里用了很巧妙的一种方法就是,我构建随机图像,然后经过过滤器,那么,当我的输入和过滤器的模式一样的时候,这样的响应是最大的,有点像模版匹配。可以利用梯度上升法,将这一层的输出相对于输入求导,然后沿着输出值最大的方向改变输入的值,使得最后的输出最大,最后得到的输入图像就是过滤器了。这部分能够看出的信息其实和第一部分是差不多的。3. 是类激活的热力图,也就是每一个像素,它预测是属于哪一种类,预测的概率是多少,这样可以看看哪些像素比较重要。该方法基于 ***Grad-CAM: visual explanations from deep networks via gradient-based localization*** 论文。主要的思路如下,卷积层的输出其实代表的就是原始图像中剩余的信息,剩余的信息就是比较重要的信息,重要性就体现在了特征图的值上,但是输出的通道很多,有512层,有128层,怎么把这些层合并成一层,然后映射到输入图像上呢。不同的层对于最后的预测结果的影响是不同的,那么按照这个影响的权重进行相加就是合理的,因此可以求出特征图中的每一层相对于最后预测的类别的梯度代表着它的重要性系数,然后把卷积层的输出进行叠加就可以了。 + +在`keras`中,其实并不是模型为导向的,平时写模型,都是基于模型的思维在计算梯度、loss函数之类的,其实还可以基于`function`来计算,通过指定输入和输出的`Tensor`,可以生成`function`,然后和模型中用到的计算思路一样,每一次输入输入,得到输出。 + +## 第六章 深度学习用于文本和序列 +### 处理文本数据 +> 将文本分解而成的单元(单词、字符、n-gram)叫做标记(token),分解的过程叫做分词(tokenization),再将分词的结果进行数值向量化,数值向量化的方法有**one-hot**编码和**token embedding** + +在图像相关的处理中,我们也会对标签进行one-hot编码,这种编码对于token比较少的情况是比较适用的,一旦量大了就会形成稀疏矩阵,这个不太好处理。 + +所谓的token embedding其实是对原始的toekn进行进一步的加工,我觉得可以理解为在one-hot的基础上对信息进行进一步的降维。 + +词向量位于词向量空间中,不同领域的词向量空间的表示是不一样的,比如法律文书和日常用语。**词向量之间的距离能够反应出不同词之间的语义差别**,比如精度和准确度,有时候是可以互换的,我们就希望它们的向量距离也非常小。同时,我们还希望**词向量是有方向的**,比如cat、dog、wolf、tiger,从cat到tiger的向量与从dog到wolf的向量相等,这个向量可以解释为从宠物到野生动物向量。当然还可以有其他的角度。 + +根据不同的目的我们会尝试去构建不同的词向量空间。 + +但是有些时候我们没有足够的数据去训练任务相关的词向量空间,这个时候就可以复用已有的结果了,因为很多的较为底层的特征是通用的。比如word2vec、GloVe等。 + +### 循环神经网络 +#### 简单的RNN +**前馈网络**处理数据的前提假设是数据都是独立的,数据和数据之间是没有什么关系的。但是对于序列数据来说,前面的数据是可以作为后面数据的前提的,数据之间是存在一定关系的。这就需要**循环神经网络**,它其实就是除了当前的状态,还需要加上前一时刻的状态,简单来说就是下面的公式 + +$$ +output_t = tanh(dot(W, input_t) + dot(U, state_t) + b) +$$ + +对于循环神经网络而言,它的返回值有两种形式,一种是把产生的中间结果也都返回,比如`$t_1$`到`$t_n$`,中间有`$t_2$`、`$t_3$`等等都返回,另一种就是只返回最后的`$t_n$`的结果。在多个循环网络进行叠加的时候,前面的训练网络要把所有的输出都返回,最后一个循环看情况要不要把所有的都返回。 + +上述的公式中存在一个问题,就是我只加入了前一时刻的信息,而随着网络不断往后,会出现梯度消失的问题,难以记住较为以前的信息,无法学习到长期依赖,没有什么实用价值。 + +#### LSTM +因此出现了**长短期记忆(LSTM)**算法。 + +理解**LSTM**算法是本章的重点。 + +通过[这篇文章](https://colah.github.io/posts/2015-08-Understanding-LSTMs/)可以很好的理解整个的工作原理,其实最本质的就是在上面的RNN网络的基础上,怎么把长期信息也加上去,不会把远点的信息给忘记。 + +首先在传统神经网络中,我们把输入数据输入到网络层中,产生结果,然后到下一层中 + +$$ +output_t = tanh(W_{ft} \dot x_t + b_t) +$$ + +然后为了把前面的信息加进来就引入了上一个输出结果的状态,构建了简单的RNN网络。 + +$$ +output_t = tanh(W_{ft} \dot ([h_{t-1}, x_t]) + b_t) +$$ + +但是这种还不够,还需要引入长期信息的记忆能力,上面的功能只是把上一层的信息传递到后面一层去,能力还是不够。所以LSTM在这个基础上增加了一条线路,可以把很远的地方的信息也输送过来。在这个基础上构建了更为复杂的LSTM网络。 + +现在就有这么几条线了:输入(`$x_t$`)、前一时刻的状态(`$h_{t-1}$`)、前序数据输送带(`$C_t$`)、输出(`$output_t$`) + +但是每一条线的信息都需要判断是否要采用,LSTM里面用了很多的所谓的`门电路`,保留这部分的信息还是过滤这部分的信息。 + +首先是前一步的`$C_{t-1}$`的信息门电路,`$f_t = \sigma(W_{ft} \dot [h_{t-1},x_t] + b_{ft})$`,这个会产生一个`$[0,1]$`范围内的值,然后和`$C_{t-1}$`相乘,可以控制这条信息流传递下去的量,这是安装的第一个阀门。 + +然后是属于该层的层操作,输入输入数据和前一时刻的状态,输出该层的运算结果,但是这个也得加一个阀门,来控制当前层提取到的信息保留多少,这部分产生的数据会和`$C_{t-1}$`层的数据相加,得到`$C_t$`。 + +第三个阀门就是控制输出,`$C_t$`产生以后一方面进入前序信息携带通道,另一方面再经过计算生成当前时刻的状态,这个状态还得再加一个阀门,控制它最后产出`$h_t$`。 + +这就是LSTM网络了,**本质上就是在简单的RNN基础上加了三个阀门** + +在用算法解决问题的时候,应该尽可能构建一个简单的模型先,然后以这个模型为基准,不断构建复杂的模型,复杂的模型至少要比基准模型好才可以。 + +在本书的观察耶拿天气数据中,首先提出了基于简单假设的方法,也就是温度时间序列是连续的,第二天的温度理论上会接近当天的温度,然后在天的角度也有周期性的波动,因此第二天的温度就等于今天的温度。然后提出基于深度学习的全连接的解决方案,结果发现第二种方法和第一种方法差不多。也就是说,如果数据到目标是一个简单且表现良好的模型,但是基于深度学习这个更复杂的模型却没有找到更简单的模型,理论上更简单的模型是包含在模型空间中的,这里面的原因是,我们并没有把更简单这个假设包括在训练过程中,所以很难学习到简单且性能良好的模型。 + +在循环神经网络中,如果和卷积神经网络中一样使用,会妨碍训练过程,并没有什么用处。循环神经网络中怎么加dropout + +#### 双向RNN +如果说一种序列,并不是强前向的,那么可以考虑把反向数据输入进行训练,说不定能提升效果,但是强正向的数据就没啥用了。 + +### 用卷积网络处理序列 +2D的卷积神经网络提取的是空间的信息,同样,可以用1D的卷积神经网络去提取序列信息,这个所谓的提取本质上其实就是信息的压缩,从冗余的低级信息中抽象出更高级的信息,1D可以依然保持信息的顺序,但是这种顺序是非常粗浅的顺序,对于一些简单一点的任务还好,复杂的就不行了。不过书中写道在音频生成和机器翻译领域取得了巨大的成功,这个就不太理解了。小型的1D卷积神经网络有个好处就是计算代价相比于RNN来说很低,因此,其实可以把1D卷积神经网络和RNN进行结合,先用1D卷积神经网络从低级信息提取出高级信息,就跟token embedding的思路一样。 + + +## 第七章 高级的深度学习最佳实践 +### 多模态模型构建 +在前面几章的,构建模型都是用的`Sequential`模块,把一层一层的`layer`叠加在一起,只有一个输入一个输出,但是实际上在构建模型的时候,常常会遇到多输入或者多输出的情况,还有一些中间比较复杂的模块,这个时候就要用到`Model`模块了。在`keras`中有两种模块,分别是`Mode`和`Network`,`Network`只包括网络的结构,而`Model`在这个基础上还包括了训练的部分。之前写代码我只关心整个的网络结构,训练的部分都是手工进行,这样写代码就有点不优雅。之前之所以手工写,是因为官网的例子都是很简单的例子,多输入多输出的情况都很少,在多种输入和输出的情况下,应该怎么计算loss,怎么把不同的输入和不同的输出进行对应,这点我没有想明白。其实很简单,就是每一层都有名字,输入输出层也有自己的名字,在输入对应数据的时候,通过`dict`类型进行赋值或对应。如下代码所示,同理可得,也可以分别计算loss。 + +``` python +brancha = Input(shape=(300,300,3), name="brancha") +branchb = Input(shape=(300,300,3), name="branchb") + +xa = Dense(32,3,activation="relu")(brancha) +xb = Dense(32,3,activation="relu")(branchb) + +x = Concatenate()([xa, xb]) + +outputa = Dense(32,3,activation="softmax", name="outputa")(x) +outputb = Dense(32,3,activation="softmax", name="outputb")(x) + +model = Model(inputs=[brancha, branchb], outpus = [outputa, outputb]) + +model.fit({"brancha":inputa,"branchb":inputb}, + {"outputa":outputa, "outputb":outputb}, + epochs=10, batch_size=10) +``` + +另一方面,我从最开始写模型是通过继承`Model`这个类,然后分别写好每一层,设置好参数,然后在`__call__`中调用这些定义好的层。这在面向对象的逻辑中是成立的,但是在这里实际操作的时候就不好操作,首先,不同模型之间的复用就会变得很麻烦,会行程模型一层嵌套一层,最后把整个代码弄的很复杂,同时这么写的话,就需要考虑自己推断从输入的shape到输出的shape,同时很多的函数也没办法调用,比如`summary()`等。所以现在我转换了策略,我依然继承`Model`,但是我在初始化的时候,通过构建输入与输出,然后把构建的`inputs`和`outputs`传入到父类中去构建出整个的模型。这样,既能根据不同的模型加入不同的参数,也能用现成的keras模型。 + +### 有用的结构和卷积 +在做卷积操作的时候,其实有两步:1.是在同一层中,用同一个卷积核遍历该特征层;2.在不同的特征层中进行运算求和。前者叫空间特征,后者叫通道特征。**1x1卷积**就是计算的通道特征,**SeparableConv**和**DepthwiseConv**就是计算的空间的特征。 + +上述提到的非线性的模块包括了Inception模块和residual模块。residual模块之所以效果这么好一方面是因为加了shortcut模块,因为在进行卷积操作的时候,其实是把一些特征丢失的,很多丢失的信号是没办法复原的。比如把音频中的低频信号去掉,就没办法恢复了。shortcut模块可以把前面的信息再加回去。另一方面这个通道也能够在反向传播的时候发挥作用,减缓出现梯度消失的情况。 + +书中还提到一种情况,虽然有两个输入,但是两个输入的属性一样,比如要评估两个句子之间的语意相似度,因为两个输入的句子是可以互换的,他们的相似度是对称关系,不能说用两个网络分别去处理,因为他们是把句子映射到同一特征空间,所以会用同一个模型去分别走两个句子,然后得到的结果再去评估句子的相似度。处理两个摄像头的特征也是同理。只不过这部分在实际的应用中我还没有见到。 + +### 回调函数 +回调函数的作用其实很多方面,有一点我没有想到,就是可以设置提前训练结束还有根据loss函数,梯度等动态调整learning rate等。 + +### 进一步提升模型的性能 +#### 批处理 +对输入数据进行标准化,可以剔除一些无关紧要的特征的影响,专注于整个图像的分布不同进行推理得到结果。从每一层的特征图出发,其实和从输入层出发一样,也需要进行标准化,可以怎么标准化,之前在ResNet中用了一组RGB的数字是统计了ImageNet的图片得到的均值和方差值。所以在`BatchNormalization`的计算中,不断更新均值等,在训练过程中保存已读取的每批的数据均值和方差的指数移动平均值,它有利于梯度传播,因此运行更深的网络。 + +#### 超参数优化 +超参数优化需要注意的点就是,我们要用验证集来调整,不要基于测试集,不然就没啥用了,容易出现过拟合。 + +文中也推荐了超参数优化的库:**Hyperopt**,它的内部使用Parzen估计器来预测哪组超参数更好。还有一种和keras结合的**Hyperas**库,也可以尝试一下。 + +#### 模型集成 +模型之所以集成,是因为不同的模型从不同的侧面反应出事物的不同方面。就像盲人摸象,一个模型摸到一个地方,另一个模型摸到另一个地方,然后集成,最后勾勒出整个大象的形状。但是也不能都摸到大象的鼻子,这样的集成是没有用的,必须要保证模型的多样性,不同的模型,偏差向不同的地方。 + +**但是,怎么去评估各个模型的得分,效果呢?**,去kaggle上多找一些例子看看。 + +## 第八章 生成式深度学习 +### 使用LSTM生成文本 +在本节中,通过LSTM网络构建模型,在网络的最后是一层softmax层,输出各个单词的概率,但是并没有直接使用这个概率,而是在这个基础上对这个概率进行了随机采样,也就是根据概率值生成样本,然后选择出现次数最多的那个,出现次数的多少取决于概率,但是每次的结果不一样,只能说出现某个值的概率更大一些。然后又引入了一个参数`$t$`,对原来的概率分布进行重排,可以用来控制生成的字符*更随机*或者*更不随机*,所谓的*更不随机*就是更加符合我们从训练样本中得到的样本空间的分布。 + +``` python +def sample(preds, t = 1.0): + preds = np.asarray(preds).astype('float64') + preds = np.log(preds) / t + exp_preds = np.exp(preds) + preds = exp_preds / np.sum(exp_preds) + probas = np.random.multinominal(1, preds, 1) + return np.argmax(probas) +``` + +倒数第二行代码其实是根据`preds`的分布来采样,会得到和`preds`的长度一样的一个数组,数组里面的数字代表的是出现在这个位置上的样本次数,我们选择出现样本次数最大的这个索引,然后找到相应的字符。 + +上述的这个参数`t`为什么能够改变原来的概率分布,**`t`的取值范围是(0,1],值越大,那么得到的熵越大,越不确定**。 + +我们来看下图 + +

指数函数 + +当我们进行`$\log$`运算以后,概率越大的部分,生成的值越小,最后处以`$t$`以后值就越大,概率大的值和概率小的值之间的差距会随着`$t$`变小而变大,然后在作用一个`$e^x$`操作,又把数值变到`$[0,1]$`之间。总结来说就是`$t$`很小的时候,原来概率越小的部分,在变换以后概率会变得更加小,大概率值与小概率值之间的差距就会变大,也就是说越来越偏向于大概率的值,最后输出的结果也就越确定,熵就会越小** + +### DeepDream +DeepDream的原理其实和之前的神经网络的可视化是差不多的,就是说神经网络通过数据的学习到了模型的参数,这个参数能从图片中提取出相关的信息。通过ImageNet训练出来的模型有非常多的分类,因此有很多针对不同物体的不同的核,我们把这些信息提取出来然后画到原来的图上去。本质上还是那一套,只不过现在是用的层数更多了,并且在不同尺度上对特征进行了综合,然后为了保证清晰度,把图片放大缩小后又不断把细节填充进去。训练过程也是一样,原来的训练过程是在一张白纸上通过梯度上升,求的响应最大值,现在也是利用梯度上升。loss函数直接求的就是指定的几个输出层,毕竟最后的结果也是求得这几层的最大响应。**为了避免出现边界伪影,只包含非边界像素**,这种做法在好几个地方都看到了。 + +### 神经风格迁移 +风格迁移的过程分为两步,一部分是我们要保存我们的目标图像的内容,这个目标图像也就是我们的输入图像,我们希望在这个图像上进行操作,同时呢,我们又想把参考图像的风格加入到我们的目标图像中,这两个分别就是图像的内容和风格的部分,抽象出来就是要保证内容损失和风格损失最小,内容风格是和目标图像进行对比,风格损失是和参考图像进行对比。内容比较好理解,我们可以选取更深层的网络层,浅层表示的是局部的浅特征,深层次的网络模型表示的是全局的更抽象的图像内容。风格其实就是图像的纹理,而所谓的纹理就是图像内部的相互关系。风格也可以在不同的纬度来表现,因此,风格的损失我们选取多层网络输出进行计算。 + +内容损失比较好计算,直接比较在深层中的网络输出的值。风格的损失要求出一张图像内部的特征关系,这里用到了所谓的Gram Matrix,其实就是求水平向量两两之间的相似度,这就是一张图片的内部关系,然后比较一下生成图像和参考图像之间的差值。**同时提到为了促使生成的图像具有空间连续性,避免结果过度像素化,增加一个总变差损失,其实就是希望前后两个像素差别不要太大,变化具有连续性,分别在`x`和`y`方向进行计算。**不同的损失值有不同的系数,用于控制更偏向于哪个方面。 + +我们在平时中用到的以`SGD`方法,这在数据量比较大的时候用处比较大,数据量比较小的时候可以选择`L-BFGS`算法。 + +### 用变分自编码器生成图像 +变分自编码器(VAE, variational autoencoder),就是把图片映射到一个向量空间,这个向量空间通过平均值和方差来表示,这个过程称之为**编码器**,然后在这个向量空间中我们选择生成的均值和方差值(这个方差值增加一些噪声),再把它还原成原来的图片,这个过程称之为**解码器**。这个就是整个模型的组成部分。这个的训练过程就是只有最后比较一下生成的图像和原始的图像之间的差距。不需要外部额外计算的其他loss,是一种不需要标注集的训练。 + +VAE得到的是高度结构化的,连续的潜在表示,比如沿着一个横截面移动,可以实现以连续的方式显示一张起始图像缓慢变化为不同图像的效果。 + +主要原因是最后的潜在空间压缩的比较厉害,所以有种类似于主成分析中,生成的分别就会趋向于连续变化的主要成分分量。 + +### 生成式对抗网络 +生成式对抗网络(GAN, generative adversarial network),它主要也是两个部分,一个是**生成器网络**,另一个是**判别器网络**,生成器网络从随机空间中选取随机数生成一幅图像,然后把这些图像和真实图像混在一起输入到判别器网络,判别器网络去判断是真是假。 + +$$ +gan = discriminator(generator(x)) +$$ + +GAN网络的训练是一个动态的过程,生成器会变化,判别器会变化。很难训练,需要对模型架构和训练参数进行很多的微调。GAN的训练方法有一些技巧,详情见该书的P259. + +GAN网络在训练的过程中要保持判别器的参数不变,判别器的训练是单独训练的,和GAN网络分开。 + +## 第九章 总结 +总的来说,现阶段的深度学习其实是局部泛化,也就是说我喂进去什么数据,只能基于这个进行简单的泛化,比如输入识别人的数据,就不能识别其他动物。而人类的意识其实是极端泛化,我们不需要反复的看很多数据,能够通过**抽象**和**推理**进行更宽泛的泛化,所以,如果要实现人类一样的智慧,现在的这种方法肯定是不行的。 + +想要实现模型的复用其实很难,模型结构可以复用,可是模型参数怎么办,模型参数是根据不同的任务训练的,是没办法复用的,所以现阶段的这种形式肯定是初级阶段的。 \ No newline at end of file diff --git a/source/_posts/sigmoid-function.md b/source/_posts/sigmoid-function.md new file mode 100644 index 00000000..7be0a574 --- /dev/null +++ b/source/_posts/sigmoid-function.md @@ -0,0 +1,169 @@ +--- +title: "机器学习实践——Logistic回归(Logistic Regression)" +date: 2018-08-26 +mathjax: true +--- + +## 0x00 问题引入 +[上一节](https://joeltsui.github.io/2018/08/24/linear-regression/)中讨论了线性回归,线性回归中`$y$`的值是连续的,有无数种可能。有些问题它的`$y$`值是离散的,可能只有两种或者三种,这类回归问题也叫分类问题。我们以二元分类为例,在二元分类中,`$y$`值有两种可能,分别叫做正样本和负样本。要实现二元分类问题其实也是求一条直线,和线性回归问题一样。对于线性回归问题,是通过已有的点去拟合一条直线,使得这条直线尽可能多的代表已有的数据点。而对于分类问题,也是通过一条直线,但是这条直线是把两个类别分开,直线的这边是正样本,直线的另一边是负样本。因此我们的任务也就变成了,寻找一条可以区分正负样本的直线。 + + +

Classification Example + + +## 0x01 问题概述与思路 +都是寻找一条直线,但是直线的目的不同,我们需要通过Loss函数或者最大似然估计函数的不同去求解不同的直线。`$y=ax+b$`得到的是连续值,取值范围根据`$x$`的不同在`$(-\infty,+\infty)$`之间。而我们只有正样本和负样本两个值,因此我们需要一个函数,可以把`$y$`值变成可以得到两个分类的值。我们常用的就是Sigmoid函数。 + +$$ +g(z) = \frac{1}{1+e^{-z}} +$$ + +因此我们的hypothes函数就是 + +$$ +h_{\theta}(x)=g(\theta^Tx)=\frac{1}{1+e^{-\theta^Tx}} +$$ + + +Sigmoid函数也叫Logistic函数。 + +

Logistic Regression + + +我们按照图1来梳理一下整个的流程。 +图1中有`$(x_1,x_2,1)$`两个自变量,一对`$(x_1^{(i)},x_2^{(i)},1),x\in[1,m]$`有一个标签对应,表示它是正样本还是负样本,最后的那个1表示的是截距,这个表达式其实和直线方程是一致的。我们现在假设有参数`$\theta=(\theta_1, \theta_2,\theta_3)$`就是我们最后的结果,也就是图中的那条直线。 + +(1)当`$(x_1^{(i)},x_2^{(i)})$`表示在直线上的点的时候`$\theta^Tx=0$`, + +(2)当`$(x_1^{(i)},x_2^{(i)})$`表示在直线下方的点时候`$\theta^Tx<0$`,并且离直线越远,`$\theta^Tx$`的值就越大。`$h_{\theta}(x)$`趋向于1。表示我们的正样本。 + +(3)当`$(x_1^{(i)},x_2^{(i)})$`表示在直线上方的点时候`$\theta^Tx>0$`,并且离直线越远,`$\theta^Tx$`的值就越小。`$h_{\theta}(x)$`趋向于0。表示我们的负样本。 + + +在利用损失函数或者最大似然估计计算参数的时候,我们并不关系函数的值的大小,我们关心的是他们的趋势。当`$(x_1^{(i)},x_2^{(i)})$`是正样本的时候,我们就希望`$h_{\theta}(x)$`越接近1越好,也就是越大越好,当`$(x_1^{(i)},x_2^{(i)})$`是负样本的时候,我们就希望`$h_{\theta}(x)$`越接近0越好,也就是越小越好,也就是`$(1-h_{\theta}(x))$`越大越好。 + +考虑到`$h_{\theta}(x)$`的表达式比较复杂,而我们又不关心绝对值,所以可以把`$h_{\theta}(x)$`和`$(1-h_{\theta}(x))$`都取`$\ln$`值。`$\ln$`函数是递增函数,因此我们的希望还是不变。 + +现在把正负样本和起来写。 + +$$ +l=y\ln{(h_{\theta}(x))}+(1-y)\ln{(1-h_{\theta}(x))} +$$ + +这个式子可以保证当为正样本(即`$y=1$`)的时候,后半部分为0,前半部分`$(h_{\theta}(x)$`越大越好,当为负样本(即`$y=0$`)的时候,前半部分为0,后半部分`$(1-h_{\theta}(x))$`越大越好。把所有的样本都加起来可以得到: + +$$ +L(\theta)=\sum_i^m[y^{i}\ln{h_\theta(x^{(i)})}+(1-y^{i})\ln(1-{h_\theta(x^{(i)})}]\tag{1} +$$ + +取`$L$`的最大值就是我们的目标。 + +按照在线性回归中的方法,通过求导求最大值。也不是说不能做,但是整个过程会变得很复杂,求导很麻烦。 + +因此我们换个思路。也就是**梯度上升法**。可以用简单一点的函数去理解,导数就是沿着某个方向变化最快的值,当到达最高点或者最低点的时候,导数为0。我们就沿着当前点的导数方向去调整`$\theta$`值,使得`$L$`往最大值的方向走。 + +对于`$y=ax+b$`函数,自变量只有一个`$x$`,因此对`$x$`求导就可以,对于`$y=ax_1+bx_2+c$`,自变量有两个,需要在`$x_1$`和`$x_2$`两个方向一起去变化,分别对`$x_1$`和`$x_2$`进行求导。 + +因此对于式(1)就需要分别对`$\theta_1,\theta_2,...,\theta_{m}$`进行求导,更新每一个`$\theta_{i}$`的值。 + +为了进一步求导,先计算 + +$$ +\frac{\partial{g(z)}}{\partial{z}}=g(z)(1-g(z)) +$$ + +上述公式推导起来很简单,不多讲。 + +以某一个`$\theta_j$`为例,求导一下。 + +$$ +\begin{split} +\frac{\partial{L(\theta)}}{\partial{\theta_j}}&=\sum_i^m[{y^{(i)}}\frac{1}{h_{\theta}(x^{(i)})}\frac{\partial{h_\theta}(x^{(i)})}{\partial{\theta_j}}-(1-y^{(i)})\frac{1}{1-h_\theta(x^{(i)})}\frac{\partial{h_\theta(x^{(i)})}}{\partial{\theta_j}}]\\ +&=\sum_i^m[{y^{(i)}}\frac{1}{h_{\theta}(x^{(i)})}-(1-y^{(i)})\frac{1}{1-h_\theta(x^{(i)})}]\frac{\partial{h_\theta}(x^{(i)})}{\partial{\theta_j}}\\ +&=\sum_i^m[{y^{(i)}}\frac{1}{h_{\theta}(x^{(i)})}-(1-y^{(i)})\frac{1}{1-h_\theta(x^{(i)})}]\frac{\partial{h_\theta(x^{(i)})}}{\partial{z}}\frac{\partial{z}}{\theta_{j}}\\ +&=\sum_i^m[{y^{(i)}}\frac{1}{h_{\theta}(x^{(i)})}-(1-y^{(i)})\frac{1}{1-h_\theta(x^{(i)})}]h_\theta(x^{(i)})(1-h_\theta(x^{(i)}))x^{(i)}_j\\ +&=\sum_i^m[y^{(i)}(1-h_{\theta}(x^{(i)}))+(y^{(i)}-1)h_{\theta}(x^{(i)})]x^{(i)}_j\\ +&=\sum_i^m[y^{(i)}-h_{\theta}(x^{(i)})]x^{(i)}_j +\end{split} +$$ + +把`$\sum$`去掉,通过向量来表示。`$y=[y^{(1)},y^{(2)},...,y^{(m)}]^T$`,`$x_j=[x^{(1)}_j,x^{(2)}_j,...,x^{(m)}_j]^T$` + +$$ +\begin{split} +\frac{\partial{L(\theta)}}{\partial{\theta_j}}&=[x_j^{(1)},x_j^{(2)},\cdots,x_j^{(m)}] +\begin{bmatrix} +y^{(1)}-h_\theta(x^{(1)})\\ +y^{(2)}-h_\theta(x^{(2)})\\ +\cdots\\ +y^{(m)}-h_\theta(x^{(m)}) +\end{bmatrix} +&=(x_j)^T(y-h_\theta(x)) +\end{split} +$$ + +$$ +\begin{split} +\frac{\partial{L(\theta)}}{\partial{\theta}}&= +\begin{bmatrix} +x_1^{(1)} & x_1^{(2)} & \cdots & x_1^{(m)}\\ +x_2^{(1)} & x_2^{(2)} & \cdots & x_2^{(m)}\\ +\cdots & \cdots & \cdots & \cdots\\ +x_n^{(1)} & x_n^{(2)} & \cdots & x_n^{(m)} +\end{bmatrix} +\begin{bmatrix} +y^{(1)}-h_\theta(x^{(1)})\\ +y^{(2)}-h_\theta(x^{(2)})\\ +\cdots\\ +y^{(m)}-h_\theta(x^{(m)}) +\end{bmatrix} +=x^T(y-h_\theta(x)) +\end{split} +$$ + +这样就可以通过不断的迭代使得`$\theta$`不断去靠近我们期望的值。 + +$$ +\theta := \theta + \alpha x^T(y-h_\theta(x)) +$$ + +上述的`$\theta=[\theta_1,\theta_2,\cdots,\theta_n]^T$`,`$x=[x^{(1)},x^{(2)},\cdots,x^{(m)}]^T$`,其中 `$x^{(i)}=[x^{(i)}_1,x^{(i)}_2,\cdots,x^{(i)}_n]$`,`$y=[y^{1},y^{(2)},\cdots,y^{(m)}]^T$`。 + +## 0x02 Coding Example +代码在[这里](http://q0qh4z3h0.bkt.clouddn.com/files/logRegres.py),数据集在[这里](http://q0qh4z3h0.bkt.clouddn.com/files/testSet.txt) + +将测试集的数据进行展示。 + +

Logistic Regression Example + +在这个例子中`$x=[x_0,x_1,1]^T$`,最后一个的1表示截距。`$\theta=[\theta_0, \theta_1, \theta_2]^T$`,正负样本分别是标签为1和0的数据。数据为`dataMatrix`,标签数据为`labelMatrix`。其中`dataMatrix`的`$shape=100 \times 3$`,`labelMatrix`的`$shape=100 \times 1$` + +``` python +def gradAscent(dataMatrix, labelMatrix): + m,n = dataMatrix.shape + theta = np.ones((n,1)) + maxCycles = 500 + alpha = 0.001 + + for k in range(maxCycles): + h = sigmoid(np.matmul(dataMatrix,theta)) + delta = np.matmul(dataMatrix.transpose(),(labelMatrix - h)) + theta = theta + alpha*delta + return theta +``` +进过计算就能得到`$\theta$`的参数值了,把`$\theta^T x=0$`直线画上去,就能得到下图了。 + +

Logistic Regression Example + +(end) + + + + + + + + + + + diff --git a/source/_posts/softmax-regression.md b/source/_posts/softmax-regression.md new file mode 100644 index 00000000..0146a485 --- /dev/null +++ b/source/_posts/softmax-regression.md @@ -0,0 +1,135 @@ +--- +title: "机器学习实践——Softmax回归(Softmax Regression)" +date: 2018-08-29 +mathjax: true +--- + +## 0x00 问题引入 +在Sigmoid回归问题中,我们梳理了二元的回归函数,但是很多时候类别是大于2的。比如需要区分0-9这10个数字,就需要10个类别。 + +其实Softmax和Logistic回归本质上是一样的。在Logistic二分类的问题中,是将特征值`$x$`先经过线性方程,再经过非线性方程,最后得到一个预测值,让预测值要么等于1,要么等于0.同样的,对于多分类的问题,我们也是让特征值先经过线性方程,再经过非线性方程,最后得到一个值。只不过现在是要得到`$k$`个值。同一套的`$\theta$`肯定是不行的,我们需要给每个分类都配`$\theta$`。假设自变量总共有`$n$`个特征,最后总共有`$k$`个分类,则`$\theta$`的`$shape=n \times k$`。但是有个问题是,每一个分类都有一个值,选哪个?此时Softmax里面的`$max$`的价值就体现出来了。就选取其中值最大的出来。相当于取概率最大的那个。我们怎么去构建这块思路,就会体现在训练出来的参数上。 + +## 0x01 问题概述与思路 + +非线性的过程我们选取`$g(\theta^Tx)=e^{\theta^Tx}$`。 +因此可以得到 + +$$ +h_\theta(x^{(i)})= +\begin{bmatrix} +p(y^{(i)}=1|x^{(i)};\theta)\\ +p(y^{(i)}=2|x^{(i)};\theta)\\ +\cdots \\ +p(y^{(i)}=k|x^{(i)};\theta) +\end{bmatrix} += +\frac{1}{\sum_{j=1}^ke^{x^{(i)}\theta_j^T}} +\begin{bmatrix} +e^{x^{(i)}\theta_1^T}\\ +e^{x^{(i)}\theta_2^T}\\ +\cdots\\ +e^{x^{(i)}\theta_k^T} +\end{bmatrix} += +\begin{bmatrix} +h_{\theta_{1}}(x^{(i)})\\ +h_{\theta_{2}}(x^{(i)})\\ +\cdots \\ +h_{\theta_{k}}(x^{(i)}) +\end{bmatrix} +$$ + +下面就是构造损失函数或者最大似然估计函数了。按照现在的情况,好像所谓的最大似然估计函数和损失函数已经不分了,最大似然估计函数加个负号就是损失函数了。 + +考虑一下我们期望的结果。当预测的分类是正确的时候,我们希望他对应的“概率值”`$h_{\theta_j}(x^{(i)})$`越接近1越好。 + +我们按照Logistic中的操作,对`$h_\theta(x^{(i)})$`取`$\log$`能够简化运算。在计算之前我们先定义好矩阵。 + +$$ +\theta= +\begin{bmatrix} +\theta_{11} & \theta_{12} & \cdots & \theta_{1n}\\ +\theta_{21} & \theta_{22} & \cdots & \theta_{2n}\\ +\cdots & \cdots & \cdots & \cdots\\ +\theta_{k1} & \theta_{k2} & \cdots & \theta_{kn} +\end{bmatrix} +$$ + +$$ +x = +\begin{bmatrix} +x^{(1)}_1 & x^{(1)}_2 & \cdots & x^{(1)}_n\\ +x^{(2)}_1 & x^{(2)}_2 & \cdots & x^{(2)}_n\\ +\cdots & \cdots & \cdots & \cdots\\ +x^{(m)}_1 & x^{(m)}_2 & \cdots & x^{(m)}_n\\ +\end{bmatrix} +$$ + +$$ +y = +\begin{bmatrix} +y^{(1)}_1 & y^{(1)}_2 &\cdots &y^{(1)}_k\\ +y^{(2)}_1 & y^{(2)}_2 &\cdots &y^{(2)}_k\\ +\cdots & \cdots & \cdots & \cdots\\ +y^{(m)}_1 & y^{(m)}_2 &\cdots &y^{(m)}_k\\ +\end{bmatrix} +$$ + +我们将`$y$`进行`$one-hot$`编码,对应的分类的`$index$`为1,其余的为0。 + +$$ +x^{(i)} \theta_l^T=\theta_{l1}^T x^{(i)}_{1}+\theta_{l2}^T x^{(i)}_2+\cdots+\theta_{ln}^T x^{(i)}_1n +$$ + +考虑一下计算最大似然估计的这个过程。有一组样本点`$(x^{(i)},y^{(i)})$`。通过这个样本点,可以计算出`$h_{\theta_l}(x^{(i)}),l\in[1,k]$`。假设`$y^{i}=s,s\in [1,k]$`。那么我们就希望`$h_{\theta_s}(x^{(i)})$`越大越好,当`$l\neq s$`时,就是属于负样本,但是这个负样本有很多种的可能,可能是除了`$s$`以外的其他值,但是概率分布上统一是`$(1- h_{\theta_s}(x^{(i)}))$`。换个角度看,其实就是还是拟合一条直线,只不过这条直线把目标标签和**其他标签**分割开来,这不就是二分类嘛。 + +$$ +J(\theta)= +\sum_{i=1}^m \sum_{l=1}^k[y^{(i)}_l \ln h_{\theta_s (x^{(i)})}+(1-y^{(i)}_l)\ln (1-h_{\theta_s(x^{(i)})})],where\ \ y^{(i)}=s +$$ + + + +再把这个问题简化一下,对于每一个样本,我们只能计算与`$y^{(i)}$`标签对应的那部分`$\theta$`值。比如当`$y^{(i)}=l$`,则我们只能更新`$\theta_l=[\theta_{l1},\theta_{l2},\cdots,\theta_{ln}]$`,。因为其他的`$\theta$`值更新并没有意义,他们虽然代表的是负样本,但是却是有很多种可能的负样本,不管往哪个方向走都是不合适的。因此最大似然估计的导数就可以简化成以下,后半部分和`$\theta_{sj}$`没有关系: + +$$ +\frac{\partial L(\theta)}{\theta_j}= +\sum_{i=1}^m[y^{(i)}_l \frac{\partial \ln h_{\theta_s(x^{(i)})}}{\theta_{sj}}],where\ \ y^{(i)}=s \tag{1} +$$ + +$$ +\begin{split} +\frac{\partial \ln h_{\theta_s(x^{(i)})}}{\partial \theta_{sj}} +&=\frac{\partial (x^{(i)}\theta_l^T-\ln{\sum_{l=1}^ke^{x^{(i)}\theta_l^T}})}{\partial \theta_{sj}}\\ +&=x_j^{(i)}-\frac{\partial \ln{\sum_{l=1}^ke^{x^{(i)}\theta_l^T}}}{\partial \theta_{sj}}\\ +&=x_j^{(i)} - \frac{x_j^{(i)} e^{x^{(i)}\theta_s^{T}}}{\sum_{l=1}^ke^{x^{(i)}\theta_l^T}}\\ +&=x^{(i)}_j(1-h_{\theta_s (x^{(i)})}) +\end{split} +$$ + +所以可以`$(1)$`式 + +$$ +\frac{\partial L(\theta)}{\theta_j}= +\sum_{i=1}^m x^{(i)}_j(1-h_{\theta_s (x^{(i)})}) +$$ + +然后按照之前的套路 + +$$ +\theta_{sj} = \theta_{sj} + \alpha \sum_{i=1}^m x^{(i)}_j(1-h_{\theta_s (x^{(i)})}) +$$ + +## 0x02 Coding Example + + + +## 0x03 参考文献 +[1] https://gist.github.com/dhammack/8071840 + +[2] http://ufldl.stanford.edu/tutorial/supervised/SoftmaxRegression/ + + + + + diff --git "a/source/_tmp/\bcmake\346\225\231\347\250\213.md" "b/source/_tmp/\bcmake\346\225\231\347\250\213.md" new file mode 100644 index 00000000..b3ae5068 --- /dev/null +++ "b/source/_tmp/\bcmake\346\225\231\347\250\213.md" @@ -0,0 +1,8 @@ + + + + +参考文献 +1. http://derekmolloy.ie/hello-world-introductions-to-cmake/ +2. https://www.jetbrains.com/help/clion/working-with-cmake.html + diff --git a/source/_tmp/2018-04-17-fakeface-tutorial.md b/source/_tmp/2018-04-17-fakeface-tutorial.md new file mode 100644 index 00000000..f7032abf --- /dev/null +++ b/source/_tmp/2018-04-17-fakeface-tutorial.md @@ -0,0 +1,19 @@ +--- +title: "FakeFace实现指南" +categories: deeplearning +lang: zh +--- + +## 0x00 + +## 0x01 训练集收集 + +## 0x02 图片预处理 +图片预处理都处理哪些东西?为什么要进行图片预处理? +我们要做的是对人脸进行替换,所以必须要把人脸先抠出来。对这部分数据进行训练才是更合适。但是,人脸是不规则的,怎么把这个提取出来,然后输入到神经网络中去呢? + + +## 0x03 模型训练 + + + diff --git a/source/_tmp/2018-05-06-linux-shell-script-tutorial.md b/source/_tmp/2018-05-06-linux-shell-script-tutorial.md new file mode 100644 index 00000000..a4607012 --- /dev/null +++ b/source/_tmp/2018-05-06-linux-shell-script-tutorial.md @@ -0,0 +1,16 @@ +--- +title: "《Linux Shell脚本攻略》读书笔记" +categories: ReID,算法 +lang: zh +--- + +## 第一章 小试牛刀 + +printf 可以接受引用文本或者由空格分隔的参数。可以使用printf + + +在Shell脚本中,两边没有空格的等号是赋值操作,加上空格的等号表示的是等量关系测试。 + +使用单引号时变量不会被扩展,变量替换不会发生在单引号中。双引号允许shell解释字符串中出现的特殊符号。 + +获取字符串的长度。${#var} \ No newline at end of file diff --git a/source/_tmp/2019-04-02-tensorflow-training.md b/source/_tmp/2019-04-02-tensorflow-training.md new file mode 100644 index 00000000..22027d37 --- /dev/null +++ b/source/_tmp/2019-04-02-tensorflow-training.md @@ -0,0 +1,53 @@ +## 碰到的问题 +### 训练的速度太慢,基本都是GPU在跑 +这个[链接](https://github.com/tensorflow/models/issues/5719#issuecomment-437323963)说可能的原因是因为batch_size设置成太大了,导致速度慢,但是他没有提,把batch_size从24设置成1,GPU的利用率有没有上去。因为你看到的速度,影响因素包括了batch_size,这个值越大,那么一次跑的越多,一个batch结束以后过掉的图片越多。 + +当batch_size为24的时候,在训练的初始阶段,GPU的利用率 + +另外也提到了可能是新版的训练有问题,采用老版的试试看。 + +老版的,batch_size=24的情况下,GPU的使用率能够维持在30%左右,说明是新版本的训练的问题!妈的。 + +### Object Detection API中config文件参数 + +config文件中有很多的参数没有搞懂,需要了解一下。 +``` +fine_tune_checkpoint_type: "detection" +``` +是从detection checkpoint还是从claasification checkpoint中恢复参数用于在训练中的初始化(参数的名称需要是兼容的)。其值可以是 'classification' 'detection',默认是'detection'。[1] +所以,其实这个值只是说明这个预训练的模型是来自于detection还是classification。但是整个的Object Detection API的项目就是用于detection的啊,所以这里的意思应该是对`detection`的过程进行参数调整还是对`classification`的参数进行调整,但是都是属于这个模型的,因为detection的过程也需要classification。 + +``` +load_all_detection_checkpoint_vars:False +``` +是否加载所有的detection checkpoint的参数,这个条件需要在`fine_tune_checkpoint_type:'detection'`的情况下才有效。如果是False,那么只有对应scope的变量才会加载,默认是False。这个所谓的**appropriate scopes**到底是指哪一块呢?[2] + +``` +from_detection_checkpoint:true +``` +根据文献[3]的说法,当传入的checkpoint是否属于detection的时候。具体文献[4]中进行了回应。 + +当`load_all_detection_checkpoint_vars:True`的时候,会出现很多的node不兼容,是不是因为之前没有加载这些node,现在加载了导致的? + + +## 模型的转换 +### 转换成tensorflow-lite兼容的浮点模型 +1. 训练模型,得到了checkpoint数据,包括meta和index两部分。 +2. 通过`export_tflite_ssd_graph.py`生成tflite兼容的frozen graph[5],**此处存在一个问题,如果没有原始的checkpoint,只有普通的frozen graph,怎么变成tflite兼容的pb?** +3. 通过`tflite_convert`对2中的模型进行进一步生成tflite模型 + +### 转换成tensorflow-lite兼容的整型模型 +文献[6]详细介绍了应该怎么生成quantized的模型。在转换的时候`change_concat_input_ranges`这个参数很重要,如果没有这个参数,就会core dump。 +使用quantized的模型,但是却发现速度更慢了,大概慢了一倍。文献[7]中有提到说是因为他们只是对ARM架构的CPU进行了优化,没有对x86的进行优化,因为没有必要。 + +实际测试,如果在训练的时候没有指明要进行quantize,后面再强制转换为quantize,得到的模型没有用处。 + +参考链接: +1. https://github.com/tensorflow/models/blob/17e923da9e8caba5dfbd58846ce75962206ffa64/research/object_detection/core/model.py#L337 +2. https://github.com/tensorflow/models/blob/17e923da9e8caba5dfbd58846ce75962206ffa64/research/object_detection/meta_architectures/ssd_meta_arch.py#L1155 +3. https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/configuring_jobs.md#model-parameter-initialization +4. https://github.com/tensorflow/models/issues/3562#issuecomment-372703559 +5. https://github.com/tensorflow/models/blob/master/research/object_detection/export_tflite_ssd_graph.py +6. https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/running_on_mobile_tensorflowlite.md +7. https://github.com/tensorflow/tensorflow/issues/2807 + diff --git a/source/_tmp/2019-04-23-kcf-learnning.md b/source/_tmp/2019-04-23-kcf-learnning.md new file mode 100644 index 00000000..419e5d7b --- /dev/null +++ b/source/_tmp/2019-04-23-kcf-learnning.md @@ -0,0 +1,27 @@ +## 问题 +KCF的论文中一直在讨论如何计算一些东西,和我们要实现的算法有什么关系。 +先摸清楚这种跟踪算法大体是一个什么样的过程,核心是利用什么,再来看背后的数学原理。 + +## 算法过程 +整个的过程分为3个部分,参数初始化、首帧初始化、更新。 +总的原理是: +首先,在首帧初始化的时候,将模版保存下来,后续更新的时候就是不断的和模版进行比较,就是基本的Correlation操作,在一张图片中,与模版相同的部分是操作后的最大值。 + +但是,物体是进行不断运动的,模版不能是一成不变的。因此,在更新的时候也会有个训练的阶段,不断更新模版。KCF的算法中,所谓的训练其实就是把现在的特征和之前的特征进行一个加权相加。 + +## 具体步骤 +1. 获取图片以及目标框坐标,从图片中提取出HOG特征。 +2. 提取HOG特征之前,要对滑动窗口进行初始化。可以自定义滑动窗口的大小,也可以使用ROI的大小,这里的ROI的大小都进行了放大。同时,尺寸大小要是偶数。如果是要提取HOG特征,则长宽还需要满足能被cell的大小整除。 +3. 确定特征的滑动窗口之后,将图像提取出来,计算HOG特征,然后对特征进行归一化,裁剪和PCA。 +4. 但是呢,只有特征也是不行的,还需要丰富特征信息,比如将图像上下左右移动一下,可以让特征更加稳定? + + +KCF的作者的文章水平和MOSSE的还是有非常明显的差距,读完KCF完全不知道他在说什么,MOSSE写的就非常明白。 + +$H$表示filter,也就是模版。$F$表示输入,新传入的图片。$G$表示输入和filter在频率域相乘计算后的结果,这个应该是不断更新的。 + + +detect的过程是:已经有了一个filter,然后我用这个filter去搜索新的图片,响应的最大值就是目标。为了能够加快这个搜索的过程,我们可以转换到频率域下进行计算。所以$G=F\odot H$就是搜索的过程,得到响应值$G$。 +然后在把响应值$G$再转换到空间域下,就能找到相似的位置了。 +首先,我们的目标就是训练一个分类器,用于判断输入的图片是否属于目标物体。这是检测的过程。 +同时,确定新的模版以后,要对分类器进行训练, \ No newline at end of file diff --git "a/source/_tmp/\345\276\205\345\206\231\346\270\205\345\215\225.md" "b/source/_tmp/\345\276\205\345\206\231\346\270\205\345\215\225.md" new file mode 100644 index 00000000..29c7b4df --- /dev/null +++ "b/source/_tmp/\345\276\205\345\206\231\346\270\205\345\215\225.md" @@ -0,0 +1,4 @@ +1. teamviewer远程的时候,如果没有显示器,会造成无法初始化界面出来。xorg没有运行。进行一些操作还导致整个界面运行不起来。 +2. 怎么实现autossh端口的自动分配自动上传? +3. cmake相关的教程,写一个系列吧 +4. 《人工智能简史》里面提到了很多的人,他们之间的关系错综复杂,又相互连接,同时早就了现在很多的成就。把这个可以梳理一下。 \ No newline at end of file diff --git a/source/favicon.png b/source/favicon.png deleted file mode 100644 index ec33a133..00000000 Binary files a/source/favicon.png and /dev/null differ diff --git a/source/images/avatar.jpg b/source/images/avatar.jpg deleted file mode 100644 index 6535c29e..00000000 Binary files a/source/images/avatar.jpg and /dev/null differ diff --git a/source/images/donate/alipayimg.png b/source/images/donate/alipayimg.png deleted file mode 100644 index 5b56667c..00000000 Binary files a/source/images/donate/alipayimg.png and /dev/null differ diff --git a/source/images/donate/wechatpayimg.png b/source/images/donate/wechatpayimg.png deleted file mode 100644 index a3939c80..00000000 Binary files a/source/images/donate/wechatpayimg.png and /dev/null differ diff --git a/source/images/favatar/SzsFox-logo.png b/source/images/favatar/SzsFox-logo.png deleted file mode 100644 index 35e2838b..00000000 Binary files a/source/images/favatar/SzsFox-logo.png and /dev/null differ diff --git a/source/images/favatar/chuangzaoshi-logo.png b/source/images/favatar/chuangzaoshi-logo.png deleted file mode 100644 index 2b85f56a..00000000 Binary files a/source/images/favatar/chuangzaoshi-logo.png and /dev/null differ diff --git a/source/images/favatar/idesign-logo.png b/source/images/favatar/idesign-logo.png deleted file mode 100644 index f90c4c13..00000000 Binary files a/source/images/favatar/idesign-logo.png and /dev/null differ diff --git a/source/images/xingqiu-qrcode.jpg b/source/images/xingqiu-qrcode.jpg deleted file mode 100644 index 23798383..00000000 Binary files a/source/images/xingqiu-qrcode.jpg and /dev/null differ diff --git a/LICENSE b/themes/pure/LICENSE similarity index 100% rename from LICENSE rename to themes/pure/LICENSE diff --git a/themes/pure/_config.yml b/themes/pure/_config.yml new file mode 100644 index 00000000..ac4fdf39 --- /dev/null +++ b/themes/pure/_config.yml @@ -0,0 +1,239 @@ +# menu +menu: + Home: . + Archives: archives # 归档 + Categories: categories # 分类 + Tags: tags # 标签 + Repository: repository # github repositories + # Books: books # 豆瓣书单 + # Links: links # 友链 + About: about # 关于 + +# Enable/Disable menu icons +menu_icons: + enable: true # 是否启用导航菜单图标 + home: icon-home-fill + archives: icon-archives-fill + categories: icon-folder + tags: icon-tags + repository: icon-project + # books: icon-book-fill + # links: icon-friendship + about: icon-cup-fill + +# rss +rss: /atom.xml + +# Site +site: + logo: + enabled: true + width: 40 + height: 40 + url: https://joeltsui-blog.oss-cn-hangzhou.aliyuncs.com/icon.jpg + title: 理想国 #页面title + favicon: https://joeltsui-blog.oss-cn-hangzhou.aliyuncs.com/icon.ico + board:

码农

# 站点公告 + copyright: true # 底部版权信息 + +# config +config: + skin: # 主题颜色 theme-black theme-blue theme-green theme-purple + layout: main-center # 布局方式 main-left main-center main-right + toc: true # 是否开启文章章节目录导航 + menu_highlight: false # 是否开启当前菜单高亮显示 + thumbnail: true # enable posts thumbnail, options: true, false + excerpt_link: Read More + +# Pagination +pagination: + number: false + prev: + alwayShow: true + next: + alwayShow: true + +# Sidebar +sidebar: right +widgets: + - board + - category + - tag + - tagcloud + - archive + - recent_posts + +# display widgets at the bottom of index pages (pagination == 2) +index_widgets: +# - category +# - tagcloud +# - archive + +# widget behavior +archive_type: 'monthly' +show_count: true + +# Fancybox +fancybox: false + +# Search +search: + insight: true # you need to install `hexo-generator-json-content` before using Insight Search + baidu: false # you need to disable other search engines to use Baidu search + +# Donate +donate: + enable: false +# # 微信打赏 +# wechatpay: +# qrcode: images/donate/wechatpayimg.png +# title: 微信支付 +# # 支付宝打赏 +# alipay: +# qrcode: images/donate/alipayimg.png +# title: 支付宝 + +# Share +# weibo,qq,qzone,wechat,tencent,douban,diandian,facebook,twitter,google,linkedin +share: + enable: true # 是否启用分享 + sites: weibo,wechat # PC端显示的分享图标 + mobile_sites: weibo,wechat # 移动端显示的分享图标 + +# Github +github: + username: joeltsui # github username + +# Comment +# Gitment +# Introduction: https://imsun.net/posts/gitment-introduction/ +comment: + type: gitalk # 启用哪种评论系统 + disqus: # enter disqus shortname here + youyan: + uid: 1783844 # enter youyan uid + livere: + uid: # enter youyan uid + gitment: + githubID: + repo: + ClientID: + ClientSecret: + lazy: false + gitalk: # gitalk. https://gitalk.github.io/ + owner: joeltsui #必须. GitHub repository 所有者,可以是个人或者组织。 + admin: joeltsui #必须. GitHub repository 的所有者和合作者 (对这个 repository 有写权限的用户)。 + repo: joeltsui.github.io #必须. GitHub repository. + ClientID: ae1aeae9d231bf54430e #必须. GitHub Application Client ID. + ClientSecret: cabc2c8374879885b8c59bac4567e3e3b2f5362a #必须. GitHub Application Client Secret. + valine: # Valine. https://valine.js.org + appid: # your leancloud application appid + appkey: # your leancloud application appkey + notify: false # mail notifier , https://github.com/xCss/Valine/wiki + verify: false # Verification code + placeholder: Just go go # comment box placeholder + avatar: mm # gravatar style + meta: nick,mail,link # custom comment header + pageSize: 10 # pagination size + visitor: false # Article reading statistic https://valine.js.org/visitor.html + +# douban 豆瓣书单 +# Api: + # https://developers.douban.com/wiki/?title=book_v2 图书 + # https://developers.douban.com/wiki/?title=movie_v2 电影 +# books: + # https://api.douban.com/v2/book/user/:name/collections?start=0&count=100 个人书单列表 +# movies: + # https://api.douban.com/v2/movie/in_theaters 正在上映的电影 + # https://api.douban.com/v2/movie/coming_soon 即将上映的电影 + # https://api.douban.com/v2/movie/subject/:id 单个电影信息 + # https://api.douban.com/v2/movie/search?q={text} 电影搜索 +# douban: +# user: # 豆瓣用户名 +# start: 0 # 从哪一条记录开始 +# count: 100 # 获取豆瓣书单数据条数 + +# PV +pv: + busuanzi: + enable: true # 不蒜子统计 + leancloud: + enable: false # leancloud统计 + app_id: # leancloud + app_key: # leancloud + +# wordcount +postCount: + enable: false + wordcount: true # 文章字数统计 + min2read: true # 阅读时长预计 + +# Plugins +plugins: + google_analytics: UA-151940991-1 # enter the tracking ID for your Google Analytics + google_site_verification: # enter Google site verification code + baidu_analytics: 4554cf1badd940edd310d2211ab8b2f3 # enter Baidu Analytics hash key + tencent_analytics: 66487444 + +# Miscellaneous +twitter: +google_plus: +fb_admins: +fb_app_id: + +kramed: + gfm: true + pedantic: false + sanitize: false + tables: true + breaks: true + smartLists: true + smartypants: true + + +# profile +profile: + enabled: true # Whether to show profile bar + avatar: images/icon.jpg + gravatar: # Gravatar email address, if you enable Gravatar, your avatar config will be overriden + author: joeltsui + author_title: Deep learning engineer + author_description: 码农。 + location: HangZhou, China + follow: http://joeltsui.github.io + # Social Links + social: + links: + github: https://github.com/joeltsui + # weibo: http://weibo.com/cofess + # twitter: https://twitter.com/iwebued + # facebook: / + # dribbble: / + # behance: https://www.behance.net/cofess + rss: atom.xml + link_tooltip: true # enable the social link tooltip, options: true, false + # My Skills + skills: + Git: ★★★☆☆ + # My Personal Links + links: + Github: https://github.com/joeltsui + # Blog: http://blog.cofess.com + # 微博: http://weibo.com/cofess + # 花瓣: http://huaban.com/cofess + # Behance: https://www.behance.net/cofess + # My Personal Labels + labels: + - C++ + - Python + - Deep Learning + - Machine Vision + # My Personal Works + works: + name: + # link: http://www.example.com + # date: 2016 + # My Personal Projects + projects: + # cofess/gulp-startpro: https://github.com/cofess/gulp-startpro + # cofess/hexo-theme-pure: https://github.com/cofess/hexo-theme-pure \ No newline at end of file diff --git a/_config.yml.example b/themes/pure/_config.yml.example similarity index 100% rename from _config.yml.example rename to themes/pure/_config.yml.example diff --git a/_source/404/index.md b/themes/pure/_source/404/index.md similarity index 100% rename from _source/404/index.md rename to themes/pure/_source/404/index.md diff --git a/_source/_data/gallery.yml b/themes/pure/_source/_data/gallery.yml similarity index 100% rename from _source/_data/gallery.yml rename to themes/pure/_source/_data/gallery.yml diff --git a/_source/_data/links.yml b/themes/pure/_source/_data/links.yml similarity index 100% rename from _source/_data/links.yml rename to themes/pure/_source/_data/links.yml diff --git a/_source/about/index.md b/themes/pure/_source/about/index.md similarity index 100% rename from _source/about/index.md rename to themes/pure/_source/about/index.md diff --git a/_source/books/index.md b/themes/pure/_source/books/index.md similarity index 100% rename from _source/books/index.md rename to themes/pure/_source/books/index.md diff --git a/_source/categories/index.md b/themes/pure/_source/categories/index.md similarity index 100% rename from _source/categories/index.md rename to themes/pure/_source/categories/index.md diff --git a/_source/links/index.md b/themes/pure/_source/links/index.md similarity index 100% rename from _source/links/index.md rename to themes/pure/_source/links/index.md diff --git a/_source/repository/index.md b/themes/pure/_source/repository/index.md similarity index 100% rename from _source/repository/index.md rename to themes/pure/_source/repository/index.md diff --git a/_source/tags/index.md b/themes/pure/_source/tags/index.md similarity index 72% rename from _source/tags/index.md rename to themes/pure/_source/tags/index.md index 9cb3728f..f85afdf5 100644 --- a/_source/tags/index.md +++ b/themes/pure/_source/tags/index.md @@ -1,5 +1,5 @@ --- -title: 标签 +title: ?? layout: tags comments: false --- diff --git a/languages/default.yml b/themes/pure/languages/default.yml similarity index 100% rename from languages/default.yml rename to themes/pure/languages/default.yml diff --git a/languages/en.yml b/themes/pure/languages/en.yml similarity index 100% rename from languages/en.yml rename to themes/pure/languages/en.yml diff --git a/languages/zh-CN.yml b/themes/pure/languages/zh-CN.yml similarity index 100% rename from languages/zh-CN.yml rename to themes/pure/languages/zh-CN.yml diff --git a/languages/zh-TW.yml b/themes/pure/languages/zh-TW.yml similarity index 100% rename from languages/zh-TW.yml rename to themes/pure/languages/zh-TW.yml diff --git a/layout/_common/footer.ejs b/themes/pure/layout/_common/footer.ejs similarity index 100% rename from layout/_common/footer.ejs rename to themes/pure/layout/_common/footer.ejs diff --git a/layout/_common/head.ejs b/themes/pure/layout/_common/head.ejs similarity index 76% rename from layout/_common/head.ejs rename to themes/pure/layout/_common/head.ejs index 42b61149..e8a650af 100644 --- a/layout/_common/head.ejs +++ b/themes/pure/layout/_common/head.ejs @@ -1,8 +1,8 @@ - <% if (theme.douban.user && page.layout === 'books') { %> - - <% } %> + + + @@ -52,8 +52,29 @@ <% } %> <%- css('css/style') %> <% if (page.mathjax) { %> - - <% } %> + + + + <% } %> <% if (theme.comment.type === 'gitment' && !is_home() && !is_category() && !is_tag() && !is_archive() && post.comments) { %> <% } %> diff --git a/layout/_common/header.ejs b/themes/pure/layout/_common/header.ejs similarity index 100% rename from layout/_common/header.ejs rename to themes/pure/layout/_common/header.ejs diff --git a/layout/_common/script.ejs b/themes/pure/layout/_common/script.ejs similarity index 100% rename from layout/_common/script.ejs rename to themes/pure/layout/_common/script.ejs diff --git a/layout/_common/social.ejs b/themes/pure/layout/_common/social.ejs similarity index 100% rename from layout/_common/social.ejs rename to themes/pure/layout/_common/social.ejs diff --git a/layout/_partial/archive-book.ejs b/themes/pure/layout/_partial/archive-book.ejs similarity index 100% rename from layout/_partial/archive-book.ejs rename to themes/pure/layout/_partial/archive-book.ejs diff --git a/layout/_partial/archive-category.ejs b/themes/pure/layout/_partial/archive-category.ejs similarity index 100% rename from layout/_partial/archive-category.ejs rename to themes/pure/layout/_partial/archive-category.ejs diff --git a/layout/_partial/archive-link.ejs b/themes/pure/layout/_partial/archive-link.ejs similarity index 100% rename from layout/_partial/archive-link.ejs rename to themes/pure/layout/_partial/archive-link.ejs diff --git a/layout/_partial/archive-list.ejs b/themes/pure/layout/_partial/archive-list.ejs similarity index 100% rename from layout/_partial/archive-list.ejs rename to themes/pure/layout/_partial/archive-list.ejs diff --git a/layout/_partial/archive-post.ejs b/themes/pure/layout/_partial/archive-post.ejs similarity index 100% rename from layout/_partial/archive-post.ejs rename to themes/pure/layout/_partial/archive-post.ejs diff --git a/layout/_partial/archive-repository.ejs b/themes/pure/layout/_partial/archive-repository.ejs similarity index 100% rename from layout/_partial/archive-repository.ejs rename to themes/pure/layout/_partial/archive-repository.ejs diff --git a/layout/_partial/archive-tag.ejs b/themes/pure/layout/_partial/archive-tag.ejs similarity index 100% rename from layout/_partial/archive-tag.ejs rename to themes/pure/layout/_partial/archive-tag.ejs diff --git a/layout/_partial/archive.ejs b/themes/pure/layout/_partial/archive.ejs similarity index 100% rename from layout/_partial/archive.ejs rename to themes/pure/layout/_partial/archive.ejs diff --git a/layout/_partial/article-about.ejs b/themes/pure/layout/_partial/article-about.ejs similarity index 100% rename from layout/_partial/article-about.ejs rename to themes/pure/layout/_partial/article-about.ejs diff --git a/layout/_partial/article.ejs b/themes/pure/layout/_partial/article.ejs similarity index 100% rename from layout/_partial/article.ejs rename to themes/pure/layout/_partial/article.ejs diff --git a/layout/_partial/item-post.ejs b/themes/pure/layout/_partial/item-post.ejs similarity index 100% rename from layout/_partial/item-post.ejs rename to themes/pure/layout/_partial/item-post.ejs diff --git a/layout/_partial/pagination.ejs b/themes/pure/layout/_partial/pagination.ejs similarity index 100% rename from layout/_partial/pagination.ejs rename to themes/pure/layout/_partial/pagination.ejs diff --git a/layout/_partial/post/category.ejs b/themes/pure/layout/_partial/post/category.ejs similarity index 100% rename from layout/_partial/post/category.ejs rename to themes/pure/layout/_partial/post/category.ejs diff --git a/layout/_partial/post/comment.ejs b/themes/pure/layout/_partial/post/comment.ejs similarity index 100% rename from layout/_partial/post/comment.ejs rename to themes/pure/layout/_partial/post/comment.ejs diff --git a/layout/_partial/post/copyright.ejs b/themes/pure/layout/_partial/post/copyright.ejs similarity index 100% rename from layout/_partial/post/copyright.ejs rename to themes/pure/layout/_partial/post/copyright.ejs diff --git a/layout/_partial/post/date.ejs b/themes/pure/layout/_partial/post/date.ejs similarity index 100% rename from layout/_partial/post/date.ejs rename to themes/pure/layout/_partial/post/date.ejs diff --git a/layout/_partial/post/donate.ejs b/themes/pure/layout/_partial/post/donate.ejs similarity index 100% rename from layout/_partial/post/donate.ejs rename to themes/pure/layout/_partial/post/donate.ejs diff --git a/layout/_partial/post/gallery.ejs b/themes/pure/layout/_partial/post/gallery.ejs similarity index 100% rename from layout/_partial/post/gallery.ejs rename to themes/pure/layout/_partial/post/gallery.ejs diff --git a/layout/_partial/post/nav.ejs b/themes/pure/layout/_partial/post/nav.ejs similarity index 100% rename from layout/_partial/post/nav.ejs rename to themes/pure/layout/_partial/post/nav.ejs diff --git a/layout/_partial/post/pv.ejs b/themes/pure/layout/_partial/post/pv.ejs similarity index 100% rename from layout/_partial/post/pv.ejs rename to themes/pure/layout/_partial/post/pv.ejs diff --git a/layout/_partial/post/tag.ejs b/themes/pure/layout/_partial/post/tag.ejs similarity index 100% rename from layout/_partial/post/tag.ejs rename to themes/pure/layout/_partial/post/tag.ejs diff --git a/layout/_partial/post/thumbnail.ejs b/themes/pure/layout/_partial/post/thumbnail.ejs similarity index 100% rename from layout/_partial/post/thumbnail.ejs rename to themes/pure/layout/_partial/post/thumbnail.ejs diff --git a/layout/_partial/post/title.ejs b/themes/pure/layout/_partial/post/title.ejs similarity index 100% rename from layout/_partial/post/title.ejs rename to themes/pure/layout/_partial/post/title.ejs diff --git a/layout/_partial/post/wordcount.ejs b/themes/pure/layout/_partial/post/wordcount.ejs similarity index 100% rename from layout/_partial/post/wordcount.ejs rename to themes/pure/layout/_partial/post/wordcount.ejs diff --git a/layout/_partial/sidebar-about.ejs b/themes/pure/layout/_partial/sidebar-about.ejs similarity index 100% rename from layout/_partial/sidebar-about.ejs rename to themes/pure/layout/_partial/sidebar-about.ejs diff --git a/layout/_partial/sidebar-toc.ejs b/themes/pure/layout/_partial/sidebar-toc.ejs similarity index 100% rename from layout/_partial/sidebar-toc.ejs rename to themes/pure/layout/_partial/sidebar-toc.ejs diff --git a/layout/_partial/sidebar.ejs b/themes/pure/layout/_partial/sidebar.ejs similarity index 100% rename from layout/_partial/sidebar.ejs rename to themes/pure/layout/_partial/sidebar.ejs diff --git a/layout/_script/_analytics/baidu-analytics.ejs b/themes/pure/layout/_script/_analytics/baidu-analytics.ejs similarity index 100% rename from layout/_script/_analytics/baidu-analytics.ejs rename to themes/pure/layout/_script/_analytics/baidu-analytics.ejs diff --git a/layout/_script/_analytics/google-analytics.ejs b/themes/pure/layout/_script/_analytics/google-analytics.ejs similarity index 100% rename from layout/_script/_analytics/google-analytics.ejs rename to themes/pure/layout/_script/_analytics/google-analytics.ejs diff --git a/layout/_script/_analytics/tencent-analytics.ejs b/themes/pure/layout/_script/_analytics/tencent-analytics.ejs similarity index 100% rename from layout/_script/_analytics/tencent-analytics.ejs rename to themes/pure/layout/_script/_analytics/tencent-analytics.ejs diff --git a/layout/_script/_comment/disqus.ejs b/themes/pure/layout/_script/_comment/disqus.ejs similarity index 100% rename from layout/_script/_comment/disqus.ejs rename to themes/pure/layout/_script/_comment/disqus.ejs diff --git a/layout/_script/_comment/gitalk.ejs b/themes/pure/layout/_script/_comment/gitalk.ejs similarity index 100% rename from layout/_script/_comment/gitalk.ejs rename to themes/pure/layout/_script/_comment/gitalk.ejs diff --git a/layout/_script/_comment/gitment.ejs b/themes/pure/layout/_script/_comment/gitment.ejs similarity index 100% rename from layout/_script/_comment/gitment.ejs rename to themes/pure/layout/_script/_comment/gitment.ejs diff --git a/layout/_script/_comment/livere.ejs b/themes/pure/layout/_script/_comment/livere.ejs similarity index 100% rename from layout/_script/_comment/livere.ejs rename to themes/pure/layout/_script/_comment/livere.ejs diff --git a/layout/_script/_comment/valine.ejs b/themes/pure/layout/_script/_comment/valine.ejs similarity index 100% rename from layout/_script/_comment/valine.ejs rename to themes/pure/layout/_script/_comment/valine.ejs diff --git a/layout/_script/_comment/youyan.ejs b/themes/pure/layout/_script/_comment/youyan.ejs similarity index 100% rename from layout/_script/_comment/youyan.ejs rename to themes/pure/layout/_script/_comment/youyan.ejs diff --git a/layout/_script/_search/baidu.ejs b/themes/pure/layout/_script/_search/baidu.ejs similarity index 100% rename from layout/_script/_search/baidu.ejs rename to themes/pure/layout/_script/_search/baidu.ejs diff --git a/layout/_script/_search/insight.ejs b/themes/pure/layout/_script/_search/insight.ejs similarity index 100% rename from layout/_script/_search/insight.ejs rename to themes/pure/layout/_script/_search/insight.ejs diff --git a/layout/_script/analytics.ejs b/themes/pure/layout/_script/analytics.ejs similarity index 100% rename from layout/_script/analytics.ejs rename to themes/pure/layout/_script/analytics.ejs diff --git a/layout/_script/comment.ejs b/themes/pure/layout/_script/comment.ejs similarity index 100% rename from layout/_script/comment.ejs rename to themes/pure/layout/_script/comment.ejs diff --git a/layout/_script/douban.ejs b/themes/pure/layout/_script/douban.ejs similarity index 100% rename from layout/_script/douban.ejs rename to themes/pure/layout/_script/douban.ejs diff --git a/layout/_script/fancybox.ejs b/themes/pure/layout/_script/fancybox.ejs similarity index 100% rename from layout/_script/fancybox.ejs rename to themes/pure/layout/_script/fancybox.ejs diff --git a/layout/_script/mathjax.ejs b/themes/pure/layout/_script/mathjax.ejs similarity index 100% rename from layout/_script/mathjax.ejs rename to themes/pure/layout/_script/mathjax.ejs diff --git a/layout/_script/pv.ejs b/themes/pure/layout/_script/pv.ejs similarity index 100% rename from layout/_script/pv.ejs rename to themes/pure/layout/_script/pv.ejs diff --git a/layout/_script/repository.ejs b/themes/pure/layout/_script/repository.ejs similarity index 100% rename from layout/_script/repository.ejs rename to themes/pure/layout/_script/repository.ejs diff --git a/layout/_script/search.ejs b/themes/pure/layout/_script/search.ejs similarity index 100% rename from layout/_script/search.ejs rename to themes/pure/layout/_script/search.ejs diff --git a/layout/_search/baidu.ejs b/themes/pure/layout/_search/baidu.ejs similarity index 100% rename from layout/_search/baidu.ejs rename to themes/pure/layout/_search/baidu.ejs diff --git a/layout/_search/index-mobile.ejs b/themes/pure/layout/_search/index-mobile.ejs similarity index 100% rename from layout/_search/index-mobile.ejs rename to themes/pure/layout/_search/index-mobile.ejs diff --git a/layout/_search/index.ejs b/themes/pure/layout/_search/index.ejs similarity index 100% rename from layout/_search/index.ejs rename to themes/pure/layout/_search/index.ejs diff --git a/layout/_search/insight.ejs b/themes/pure/layout/_search/insight.ejs similarity index 100% rename from layout/_search/insight.ejs rename to themes/pure/layout/_search/insight.ejs diff --git a/layout/_search/swiftype.ejs b/themes/pure/layout/_search/swiftype.ejs similarity index 100% rename from layout/_search/swiftype.ejs rename to themes/pure/layout/_search/swiftype.ejs diff --git a/layout/_widget/archive.ejs b/themes/pure/layout/_widget/archive.ejs similarity index 100% rename from layout/_widget/archive.ejs rename to themes/pure/layout/_widget/archive.ejs diff --git a/layout/_widget/board.ejs b/themes/pure/layout/_widget/board.ejs similarity index 100% rename from layout/_widget/board.ejs rename to themes/pure/layout/_widget/board.ejs diff --git a/layout/_widget/category.ejs b/themes/pure/layout/_widget/category.ejs similarity index 100% rename from layout/_widget/category.ejs rename to themes/pure/layout/_widget/category.ejs diff --git a/layout/_widget/recent_posts.ejs b/themes/pure/layout/_widget/recent_posts.ejs similarity index 100% rename from layout/_widget/recent_posts.ejs rename to themes/pure/layout/_widget/recent_posts.ejs diff --git a/layout/_widget/tag.ejs b/themes/pure/layout/_widget/tag.ejs similarity index 100% rename from layout/_widget/tag.ejs rename to themes/pure/layout/_widget/tag.ejs diff --git a/layout/_widget/tagcloud.ejs b/themes/pure/layout/_widget/tagcloud.ejs similarity index 100% rename from layout/_widget/tagcloud.ejs rename to themes/pure/layout/_widget/tagcloud.ejs diff --git a/layout/about.ejs b/themes/pure/layout/about.ejs similarity index 100% rename from layout/about.ejs rename to themes/pure/layout/about.ejs diff --git a/layout/archive.ejs b/themes/pure/layout/archive.ejs similarity index 100% rename from layout/archive.ejs rename to themes/pure/layout/archive.ejs diff --git a/layout/books.ejs b/themes/pure/layout/books.ejs similarity index 100% rename from layout/books.ejs rename to themes/pure/layout/books.ejs diff --git a/layout/categories.ejs b/themes/pure/layout/categories.ejs similarity index 100% rename from layout/categories.ejs rename to themes/pure/layout/categories.ejs diff --git a/layout/category.ejs b/themes/pure/layout/category.ejs similarity index 100% rename from layout/category.ejs rename to themes/pure/layout/category.ejs diff --git a/layout/index.ejs b/themes/pure/layout/index.ejs similarity index 100% rename from layout/index.ejs rename to themes/pure/layout/index.ejs diff --git a/layout/layout.ejs b/themes/pure/layout/layout.ejs similarity index 100% rename from layout/layout.ejs rename to themes/pure/layout/layout.ejs diff --git a/layout/links.ejs b/themes/pure/layout/links.ejs similarity index 100% rename from layout/links.ejs rename to themes/pure/layout/links.ejs diff --git a/layout/page.ejs b/themes/pure/layout/page.ejs similarity index 100% rename from layout/page.ejs rename to themes/pure/layout/page.ejs diff --git a/layout/post.ejs b/themes/pure/layout/post.ejs similarity index 100% rename from layout/post.ejs rename to themes/pure/layout/post.ejs diff --git a/layout/repository.ejs b/themes/pure/layout/repository.ejs similarity index 100% rename from layout/repository.ejs rename to themes/pure/layout/repository.ejs diff --git a/layout/tag.ejs b/themes/pure/layout/tag.ejs similarity index 100% rename from layout/tag.ejs rename to themes/pure/layout/tag.ejs diff --git a/layout/tags.ejs b/themes/pure/layout/tags.ejs similarity index 100% rename from layout/tags.ejs rename to themes/pure/layout/tags.ejs diff --git a/themes/pure/package.json b/themes/pure/package.json new file mode 100644 index 00000000..c77a9a11 --- /dev/null +++ b/themes/pure/package.json @@ -0,0 +1,8 @@ +{ + "name": "hexo-theme-pure", + "version": "0.0.1", + "private": true, + "devDependencies": { + + } +} diff --git a/screenshot/pure-theme-black.png b/themes/pure/screenshot/pure-theme-black.png similarity index 100% rename from screenshot/pure-theme-black.png rename to themes/pure/screenshot/pure-theme-black.png diff --git a/screenshot/pure-theme-blue.png b/themes/pure/screenshot/pure-theme-blue.png similarity index 100% rename from screenshot/pure-theme-blue.png rename to themes/pure/screenshot/pure-theme-blue.png diff --git a/screenshot/pure-theme-green.png b/themes/pure/screenshot/pure-theme-green.png similarity index 100% rename from screenshot/pure-theme-green.png rename to themes/pure/screenshot/pure-theme-green.png diff --git a/screenshot/pure-theme-purple.png b/themes/pure/screenshot/pure-theme-purple.png similarity index 100% rename from screenshot/pure-theme-purple.png rename to themes/pure/screenshot/pure-theme-purple.png diff --git a/screenshot/pure.png b/themes/pure/screenshot/pure.png similarity index 100% rename from screenshot/pure.png rename to themes/pure/screenshot/pure.png diff --git a/screenshot/pure.psd b/themes/pure/screenshot/pure.psd similarity index 100% rename from screenshot/pure.psd rename to themes/pure/screenshot/pure.psd diff --git a/scripts/thumbnail.js b/themes/pure/scripts/thumbnail.js similarity index 100% rename from scripts/thumbnail.js rename to themes/pure/scripts/thumbnail.js diff --git a/source/css/style.css b/themes/pure/source/css/style.css similarity index 100% rename from source/css/style.css rename to themes/pure/source/css/style.css diff --git a/source/css/style.min.css b/themes/pure/source/css/style.min.css similarity index 100% rename from source/css/style.min.css rename to themes/pure/source/css/style.min.css diff --git a/source/fonts/README.md b/themes/pure/source/fonts/README.md similarity index 100% rename from source/fonts/README.md rename to themes/pure/source/fonts/README.md diff --git a/source/fonts/iconfont.eot b/themes/pure/source/fonts/iconfont.eot similarity index 100% rename from source/fonts/iconfont.eot rename to themes/pure/source/fonts/iconfont.eot diff --git a/source/fonts/iconfont.svg b/themes/pure/source/fonts/iconfont.svg similarity index 100% rename from source/fonts/iconfont.svg rename to themes/pure/source/fonts/iconfont.svg diff --git a/source/fonts/iconfont.ttf b/themes/pure/source/fonts/iconfont.ttf similarity index 100% rename from source/fonts/iconfont.ttf rename to themes/pure/source/fonts/iconfont.ttf diff --git a/source/fonts/iconfont.woff b/themes/pure/source/fonts/iconfont.woff similarity index 100% rename from source/fonts/iconfont.woff rename to themes/pure/source/fonts/iconfont.woff diff --git a/themes/pure/source/images/icon.ico b/themes/pure/source/images/icon.ico new file mode 100644 index 00000000..36b8cca4 Binary files /dev/null and b/themes/pure/source/images/icon.ico differ diff --git a/themes/pure/source/images/icon.jpg b/themes/pure/source/images/icon.jpg new file mode 100644 index 00000000..86fa33f1 Binary files /dev/null and b/themes/pure/source/images/icon.jpg differ diff --git a/source/images/thumb-default.png b/themes/pure/source/images/thumb-default.png similarity index 100% rename from source/images/thumb-default.png rename to themes/pure/source/images/thumb-default.png diff --git a/source/js/application.js b/themes/pure/source/js/application.js similarity index 100% rename from source/js/application.js rename to themes/pure/source/js/application.js diff --git a/source/js/application.min.js b/themes/pure/source/js/application.min.js similarity index 100% rename from source/js/application.min.js rename to themes/pure/source/js/application.min.js diff --git a/source/js/insight.js b/themes/pure/source/js/insight.js similarity index 100% rename from source/js/insight.js rename to themes/pure/source/js/insight.js diff --git a/source/js/jquery.min.js b/themes/pure/source/js/jquery.min.js similarity index 100% rename from source/js/jquery.min.js rename to themes/pure/source/js/jquery.min.js diff --git a/source/js/plugin.js b/themes/pure/source/js/plugin.js similarity index 100% rename from source/js/plugin.js rename to themes/pure/source/js/plugin.js diff --git a/source/js/plugin.js.map b/themes/pure/source/js/plugin.js.map similarity index 100% rename from source/js/plugin.js.map rename to themes/pure/source/js/plugin.js.map diff --git a/source/js/plugin.min.js b/themes/pure/source/js/plugin.min.js similarity index 100% rename from source/js/plugin.min.js rename to themes/pure/source/js/plugin.min.js