Attention_Model

Attention Model

Attention Mechanism 是近两年深度学习前沿的一个研究方向 传统的深度学习模型的主要不同, attend 模型在网络会在网络运行时, 会关注图像或文字中的某个区域, 作为判断的上下文 本次选取的论文是过去一年引用最多的一篇文章 Show, attend and tell: Neural image caption generation with visual attention . 这篇论文首次提供了关于attend 机制如何地用于 Caption(为图像生成文本描述)的详细介绍(如图1), 并取得了当时的最佳效果(state-of-the-art). 现在attention 机制已经越来越多地引用到了各个方面之中, 在CS231n 课程中, karpathy 十分推崇这个模型, 为attentin机制用与现有模型总会取得更好的效果. 并推荐在几乎所有的深度学习模型中使用(just using it everywhere)


main

图1 Words/Image alignment model

概述 背景 目标

这篇论文主要介绍的是如何利用attention 机制, 图片生成自然准确地语言描述. 深度学习流行之前, 传统的图像学者使用了一些图像识别, 位置判定等方法, 效果十分之差. 几年前, 深度学习开始用于了captioning, 主流的方法是利用 R-CNN 进行图像检测和定位, RNN进行语言生成, 两部分的网络之间的训练相对独立, karpathy和FeifeiLi 的BRNN是Attention Model
之前最佳模型, 就是由R-CNN 和 Bi-RNN相结合 .

算法介绍

Attention Model 构建在LSTM(RNN的一个改进版)和VGG(经典CNN网络) 之上, 但整个网络结构更像是一个RNN, 而不是传统的线性结构的CNN. RNN网络的每一个单元结构如图2:


enter image description here

图2 网络的Computation Graph

网络前向传播的算法如下:

  1. 将图片输入训练好的VGG 网络, 提取图片特征a: 论文中提取的低层的卷积层的输出 a, 属于比较浅层的特征. a是一个向量的集合, 每一个向量表征图片的不同特征.
  2. 根据系统状态, 决定attention区域: 一个专门的Attention function 根据上一个时刻的状态($h_{t-1}$)和图像特征 a, 计算α, α是一个向量, 和a的形状一致. $\alpha_i$用来表征网络当前状态下对图片的某一个特征($α_i$)的关注程度.
  3. αa通过一个函数$\phi$, 算得到了网络的上下文$z_t$: $\phi$函数在论文中有两个不同的选择.
  4. 将$zt$, $c{t-1}$, h_{t-1}$通过LSTM 计算得到$h_t$和$c_t$:  $h_t$和$c_t$是LSTM中的两个输出, 分别表示memory 和hidden state.
  5. 将$h_t$ 传入translate单元, 计算词向量$y_t$,
  6. 把$h_t$和$c_t$ 传入下一个单元, 返回第二步 继续生成词向量.

显然这篇论文的最大改进之处就在于用Attention Model 生成的α反复的查看图片I, 这样每次生成每个单词的描述的时候, 网络的关注点都不一样. 这种多次并且有侧重的关注, 得模型相对与传统的网络结构能更好地提取特征.

Soft AttentionHard Attention

在算法的第三步之中, 提到过函数$\phi$有不同的选取, 在论文中讲了两个不同的选取方法:
第一种选取方法 :
$$
\begin{align}
p(&s{t, } = 1 \mid s{j<t}, a ) = \alpha_{t, } \
\phi(&\alpha,a )= \hat{z}_t = \sumi {s}{t, }a_{i}.
\end{align}
$$
也就是对每一个区域$a_i$要么关注, 要么不关注, 关注与否按概率$\alpha_i$来取舍, 类似于采样. 这种方法称之为 Hard Attention.

第二种选取方法:
$$\phi(\alpha, a)= \mathbb{E}_{p(s_t|a)}[\hat{z}t] = \sum{i=1}^L \alpha{t, } a{i} $$.
对每个图像子区域都关注, 每个子区域加权之后的结果作为图像的上下文, 这种方法称之为Soft Attention.

相比较与Hard Attention, Soft Attention 效果不差太多, 但在训练时可以直接求导, 利用梯度的反向传播, 工程上更容易实现. 而Hard Attention 方法, 无法使用梯度下降方法, 需要利用强化学习(reinforcement learning!), 文中还用到了蒙特卡罗方法用于采样.

实验效果

效果很好, 如图三所示. 论文提供了源代码, 验证了模型(Hard-AttentionSoft-Attention)在三个最基准数据集 : Flickr9k, Flickr30k 和 MS COCO 都取得了当时(2015)最佳结果(state-of-the-art performance ),


论文效果

图3 模型效果

总结感想

Attention Model 这个想法特别的新奇:

一方面, 这种模型与人脑的工作机制极其相似, 人在看东西的时候在不同的时候会关注不同的地方, Attention Model也是如此, 这种模型使得神经网络离人脑更进了一步.

另一方面, 与之前caption做法不一样的是, 论文采用了一种端到端(end-to-end)的学习方式, 图像部分和自然语言处理部分直接相联, 通过缩减人工预处理和后续处理,尽可能使模型从原始输入到最终输出,给模型更多可以根据数据自动调节的空间,增加模型的整体契合度。

Attention Mechanism并不是这篇论文首创, 但是这篇论文却是Attention Model 的代表之作, 除了这篇论文详细清晰的思路之外, 最主要的还是因为这篇论文证明了Attention Model 在工程上所具有的巨大优势. 现在Attention Model 已经被用到了深度学习的方法面面, 可以预见, 未来几年Attention Model 会是一个重要的研究方向.

android反编译技术总结

android apk 破解技术总结

1 反编译得到java代码

首先要下载两个工具:dex2jar和JD-GUI
前者是将apk中的classes.dex转化成Jar文件,而JD-GUI是一个反编译工具,可以直接查看Jar包的源代码。

  • 首先将apk文件,将后缀改为zip,解压,得到其中的classes.dex,它就是java文件编译再通过dx工具打包而成的;
  • 利用dex2jar 将classes.dex 转为jar包:

    1
    path/to/dex2jar.sh ./com.hf_5.1.6_56.apk_FILES/classes.dex
  • 利JD-GUI查看并保存成java源代码
    用jd-gui打开jar包,然后全部另存为java文件,绝大多数应该都能生成java代码,但是有部分可能无法反编译成java代码。利用JD-GUI可以查看jar包中到代码,但是查找功能有限。

此外还有APKTool,但是apktool 反编译得到的是smali代码。Android采用的是java语言 进行开发,但是Android系统有自己的虚拟机Dalvik,代码编译最终不是采用的java的class,而是使用的smali,smali不易读,因此一般不适用apktool反编译成smali

2 阅读源代码

阅读源代码主要分为两个部分

  1. 关键字查找: 将java源代码的文件夹用sublime 或java IDE打开,利用正则表达式,查找所需的关键字,在本次项目中是要寻找RESTful接口,因此把url作为关键字,可以找到与此RESTful接口相关到java处理代码。

  2. 追踪方法或类的使用情况。 由于代码的加密和混淆的原因,利用IDE自身的功能,难以查找某一个方法在那些地方被使用,往往需要根据字符串匹配来实现。
    比如 查找包 com.a.b.b 中的某个类c的方法 d的使用情况,直接点击d方法,IDE一般无法找到所有d的使用地方。因此可以尝试下面两种方法

    1. 搜索 import com.a.b.b.c 在找到的java文件中查看d方法的使用情况
    2. 在com/a/b/b/ 目录下 的java文件寻找c.d((如果d是静态方法),或者寻找new c(

3 利用jar包编写程序

一般来说,我们需要使用apk中某些方法,因此在找到我们所需要的方法之后,我们

  • 新建一个项目,把jar包加入到项目的library中
  • 把android.jar 也加入到项目的libray中。 因为作为android apk,项目中的文件经常会使用到android的一些类,虽然android的类一般不会直接作用与这个函数,但是当java 文件中出现import android.app.Application时就会报错,所以为了方便省事,还是应该把android.jar 加入到项目的libray中。
  • 有些时候我们想要修改jar包中的某些函数, 比如某个函数在执行的时候需要获取android 的Context 对象,但是这个对象却不是我们所关心的,因此我们需要修改这个函数,以便我们使用。但是修改完java代码却无法将其重新编译回jar包,因此备选的做法时,把需要修改的那部分代码全部拷贝出来,新建一个包。

我们经常需要尝试jar包中的某些函数的功能,但是为每一个函数都写一个测试文件又显得麻烦,而且在弄清楚jar包中函数的参数,类的方法之前,测试类也不好写。因此建议利用REPL来测试。java目前还不支持REPL ,但是有如下三种解决方法

  • 利用groovy ,Groovy是一种基于JVM(Java虚拟机)的敏捷开发语言,可以很方便的读取jar包,并访问其中的函数和类
  • 利用scala
  • 安装jdk9 ,利用jdk9中带的 jshelljshell是java自带的REPL,不过还不成熟

傻瓜函数式编程

很古老的一片文章,但是真的写的很好

傻瓜函数式编程
from : https://github.com/justinyhuang/Functional-Programming-For-The-Rest-of-Us-Cn/blob/master/FunctionalProgrammingForTheRestOfUs.cn.md

2006年6月19日,星期一

[toc]

开篇

我们这些码农做事都是很拖拉的。每天例行报到后,先来点咖啡,看看邮件还有RSS订阅的文章。然后翻翻新闻还有那些技术网站上的更新,再过一遍编程论坛口水区里那些无聊的论战。最后从头把这些再看一次以免错过什么精彩的内容。然后就可以吃午饭了。饭饱过后,回来盯着IDE发一会呆,再看看邮箱,再去搞杯咖啡。光阴似箭,可以回家了……
(在被众人鄙视之前)我唯一想说的是,在这些拖拉的日子里总会时不时读到一些不明觉厉的文章。如果没有打开不应该打开的网站,每隔几天你都可以看到至少一篇这样的东西。它们的共性:难懂,耗时,于是这些文章就慢慢的堆积成山了。很快你就会发现自己已经累积了一堆的收藏链接还有数不清的PDF文件,此时你只希望隐入一个杳无人烟的深山老林里什么也不做,用一年半载好好的消化这些私藏宝贝。当然,我是说最好每天还是能有人来给送吃的顺带帮忙打扫卫生倒垃圾,哇哈哈。

我不知道你都收藏了些什么,我的阅读清单里面相当大部分都是函数式编程相关的东东:基本上是最难啃的。这些文章充斥着无比枯燥的教科书语言,我想就连那些在华尔街浸淫10年以上的大牛都无法搞懂这些函数式编程(简称FP)文章到底在说什么。你可以去花旗集团或者德意志银行找个项目经理来问问1:你们为什么要选JMS而不用Erlang?答案基本上是:我认为这个学术用的语言还无法胜任实际应用。可是,现有的一些系统不仅非常复杂还需要满足十分严苛的需求,它们就都是用函数式编程的方法来实现的。这,就说不过去了。
关于FP的文章确实比较难懂,但我不认为一定要搞得那么晦涩。有一些历史原因造成了这种知识断层,可是FP概念本身并不难理解。我希望这篇文章可以成为一个“FP入门指南”,帮助你从指令式编程走向函数式编程。先来点咖啡,然后继续读下去。很快你对FP的理解就会让同事们刮目相看了。

什么是函数式编程(Functional Programming,FP)?它从何而来?可以吃吗?倘若它真的像那些鼓吹FP的人说的那么好,为什么实际应用中那么少见?为什么只有那些在读博士的家伙想要用它?而最重要的是,它母亲的怎么就那么难学?那些所谓的closure、continuation,currying,lazy evaluation还有no side effects都是什么东东(译者:本着保留专用术语的原则,此处及下文类似情形均不译)?如果没有那些大学教授的帮忙怎样把它应用到实际工程里去?为什么它和我们熟悉的万能而神圣的指令式编程那么的不一样?
我们很快就会解开这些谜团。刚才我说过实际工程和学术界之间的知识断层是有其历史原因的,那么就先让我来解释一下这个问题。答案,就在接下来的一次公园漫步中:

函数式编程范式(3):实战举例

快速排序

快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

python命令式版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def sub_sort(array,low,high):
key = array[low]
while low < high:
while low < high and array[high] >= key:
high -= 1
while low < high and array[high] < key:
array[low] = array[high]
low += 1
array[high] = array[low]
array[low] = key
return low
def quick_sort(array,low,high):
if low < high:
key_index = sub_sort(array,low,high)
quick_sort(array,low,key_index)
quick_sort(array,key_index+1,high)

python 函数式版本

1
2
3
4
5
def q_sort(l):
if l == []: return []
less = filter(lambda x: x < l[0], l[1:])
more = filter(lambda y: y >= l[0], l[1:])
return q_sort(less) + [l[0]] + q_sort(more)

scala 版本

1
2
3
4
5
def quickSort(xs: List[Int]): List[Int] = {
if (xs.isEmpty) xs
else
quickSort(xs.filter(x=>x<xs.head)):::xs.head::quickSort(xs.filter(x=>x>xs.head))
}

Haskell版本:

1
2
3
q_sort n=case n of
[]->[]
(x:xs)->q_sort [a|a<-xs,a<=x]++[x]++q_sort [a|a<-xs,a>x]

$${ a| a \in N ,a <10} $$

Haskell 版本2

1
2
3
4
5
6
7
quicksort :: Ord a => [a] -> [a]
quicksort [] = []
quicksort (p:xs) =
(quicksort lesser) ++ [p] ++ (quicksort greater)
where
lesser = filter (< p) xs
greater = filter (>= p) xs

函数式编程范式(2):特点

函数式编程的特点

1 函数是一等公民

在函数式编程中,函数而是指数学中的函数,即自变量的映射,其输出仅取决于输入的参数,而和调用函数的次序无关。在函数式语言中,函数作为一等公民,可以在任何地方定义,在函数内或函数外,可以作为函数的参数和返回值,可以对函数进行组合。为了和命令式编程中的函数区分开来,通常这种函数通常称为纯函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def pure_function(x):
'''
纯函数,输入只和输出有关
'''
return x+2
y=2
def usual_function(x):
return x+y
print u'纯函数的输出 %s,%s' %(pure_function(0),pure_function(0))
print u'有副作用的函数 %s' %usual_function(0)
y=0
print u'有副作用的函数 %s' %usual_function(0)
纯函数的输出 2,2
有副作用的函数 2
有副作用的函数 0

1.1 高阶函数

函数是函数式编程的第一型,我们在函数式编程中努力用函数来表达所有的概念,完成所有的操作。
在面向对象编程中,我们把对象传来传去,那在函数式编程中,我们要做的是把函数传来传去,而这个,说成术语,我们把他叫做高阶函数。

函数式编程范式(1):历史与概述

@author chenyun

草稿

定义

函数式编程(英语:functional programming)或称函数程序设计,又称泛函编程,是一种编程范型,它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。函数编程语言最重要的基础是λ演算(lambda calculus)。而且λ演算的函数可以接受函数当作输入和输出。

历史

函数式编程中最古老的例子莫过于1958年被创造出来的LISP了。但是要提及函数式编程的例子却不得不从更早的λ演算说起。

图灵和阿隆佐·邱奇
是否存在一个通用模型来解决一切计算任务?1936年,阿隆佐·邱奇设计了一个名为lambda演算的形式系统。这个系统实质上是为一个超级机器设计的编程语言。在这种语言里面,函数的参数是函数,返回值也是函数。这种函数用希腊字母lambda(λ),这种系统因此得名。
除了阿隆佐,艾伦·图灵也在进行类似的研究。他设计了一种完全不同的系统(后来被称为图灵机),并用这种系统得出了和阿隆佐相似的答案。到了后来人们证明了图灵机和lambda演算的能力是一样的。有关lambda演算的支持请查阅维基百科

1949年第一台电子离散变量自动计算机诞生并取得了巨大的成功。它是冯·诺伊曼设计架构的第一个实例,也是一台现实世界中实现的图灵机。到了50年代末,一个叫John McCarthy的MIT教授(他也是普林斯顿的硕士)对阿隆佐的成果产生了兴趣。1958年他发明了一种列表处理语言(Lisp),这种语言是一种阿隆佐lambda演算在现实世界的实现,而且它能在冯·诺伊曼计算机上运行!很多计算机科学家都认识到了Lisp强大的能力。1973年在MIT人工智能实验室的一些程序员研发出一种机器,并把它叫做Lisp机。于是阿隆佐的lambda演算也有自己的硬件实现了!

特点概述

在函数式语言中,函数(lambda 演算)作为一等公民,可以在任何地方定义,在函数内或函数外,可以作为函数的参数和返回值,可以对函数进行组合。

函数式编程中的函数这个术语不是指计算机中的函数(实际上是Subroutine 子程序),而是指数学中的函数,即自变量的映射。也就是说一个函数的值仅决定于函数参数的值,不依赖其他状态。比如sqrt(x)函数计算x的平方根,只要x不变,不论什么时候调用,调用几次,值都是不变的。

与函数式编程对应的是命令式编程,命令式编程是面向计算机硬件的抽象,有变量(对应着存储单元),赋值语句(获取,存储指令),表达式(内存引用和算术运算)和控制语句(跳转指令).

命令式程序就是一个冯诺依曼机的指令序列.

用docker搭建spark集群

第一步 从docker官方仓库下载docker镜像

docker pull epahomov/docker-spark

第二步 启动master

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bash# docker run -d -t -P -i --name spark_master epahomov/docker-spark
bash# docker attach spark_master
#编辑 docker 的master 启动脚本
root@40defc1fa605:/# vi spark-shell.sh
----172.17.0.3 为本机的ip
#!/usr/bin/env bash
export SPARK_LOCAL_IP=`awk 'NR==1 {print $1}' /etc/hosts`
/remove_alias.sh # problems with hostname alias, see https://issues.apache.org/jira/browse/SPARK-6680
cd /usr/local/spark
./bin/spark-shell \
--master spark://172.17.0.3:7077 \
-i 172.17.0.3 \
--properties-file /spark-defaults.conf \
"$@"
-----
# 启动master
root@3746e21dff30:/# ./start-master.sh

第三步 启动worker

1
2
3
docker run -d -t -P -i --name spark_worker1 epahomov/docker-spark
docker attach spark_worker1

配置master-ip 172.17.0.4 为本机ip,172.17.0.3为master ip

1
2
3
4
5
6
7
8
9
root@40defc1fa605:/# cat ./start-worker.sh
#!/usr/bin/env bash
cd /usr/local/spark
export SPARK_LOCAL_IP=`awk 'NR==1 {print $1}' /etc/hosts`
./bin/spark-class org.apache.spark.deploy.worker.Worker \
spark://172.17.0.3:7077 \
--properties-file /spark-defaults.conf \
-i 172.17.0.4 \
"$@"

启动worker
./start-worker.sh

可以启动多台worker

打开master:8080 可以查看集群部署情况
enter image description here

在master 中打开spark-shell 就可以进行编程了

python:闭包

简单说,闭包就是根据不同的配置信息得到不同的结果

再来看看专业的解释:闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,
即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。

python:装饰器

@refer 廖雪峰
@refer xianhu

装饰器基础

装饰器的定义

1
2
3
4
5
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper

装饰器的使用

1
2
3
@log
def now():
print('2015-3-25')

@log 相当于返回log(now) 这也是一个函数,对象, 具有和now相同的参数

本质上,decorator就是一个返回函数的高阶函数。

linux: iptables 使用笔记

iptables 使用笔记

@refer http://blog.chinaunix.net/uid-26495963-id-3279216.html
@refer http://www.linuxso.com/linuxpeixun/10332.html

前言

iptables 是与最新的 3.5 版本 Linux 内核集成的 IP 信息包过滤系统
他们都是工作在用户空间中,定义规则的工具,本身并不算是防火墙。它们定义的规则,可以让在内核空间当中的netfilter来读取,并且实现让防火墙工作。而放入内核的地方必须要是特定的位置,必须是tcp/ip的协议栈经过的地方。而这个tcp/ip协议栈必须经过的地方,可以实现读取规则的地方就叫做 netfilter.(网络过滤器)

作者一共在内核空间中选择了5个位置,
1.内核空间中:从一个网络接口进来,到另一个网络接口去的
2.数据包从内核流入用户空间的
3.数据包从用户空间流出的
4.进入/离开本机的外网接口
5.进入/离开本机的内网接口

从上面的发展我们知道了作者选择了5个位置,来作为控制的地方,但是你有没有发现,其实前三个位置已经基本上能将路径彻底封锁了,但是为什么已经在进出的口设置了关卡之后还要在内部卡呢? 由于数据包尚未进行路由决策,还不知道数据要走向哪里,所以在进出口是没办法实现数据过滤的。所以要在内核空间里设置转发的关卡,进入用户空间的关卡,从用户空间出去的关卡。那么,既然他们没什么用,那我们为什么还要放置他们呢?因为我们在做NAT和DNAT的时候,目标地址转换必须在路由之前转换。所以我们必须在外网而后内网的接口处进行设置关卡。