2017年12月26日星期二

lua基础语法回顾

1.lua 数据类型

数据类型描述
nil这个最简单,只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)。
boolean包含两个值:false和true。
number表示双精度类型的实浮点数
string字符串由一对双引号或单引号来表示
function由 C 或 Lua 编写的函数
userdata表示任意存储在变量中的C数据结构
thread表示执行的独立线路,用于执行协同程序
tableLua 中的表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字或者是字符串。在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。
可以用type测试给定的变量或值的类型


1.1 nil
nil类型表示一种没有任何有效值,他只有一个nil值
nil还有删除作用,给全局变量或table里变量赋一个nil值,就等同于删掉他
tab1 = {key1 = "val1", key2 = "val2", "val3"}
for k, v in pairs(tab1) do
    print(k..'-'..v)
end

tab1.key1 = nil
for k, v in pairs(tab1) do
    print(k..'-'..v)
end

.. 用于连接字符串

1.2 boolean(true, false)

1.3 number(number类型-double双精度)【2, 2.2, 0.2...】

 1.4 string(字符串)
string1 = "this is string1"
html = [[
<html>
<head></head>
<body>
    <a href="http://www.baidu.com">百度</a>
</body>
</html>
]]
print(html)

#string1 用于测试字符串长度

1.5 table
-- 创建一个空的table
local tbl1 = {}
-- 直接初始表
local tbl2 = {"apple", "pear", "orange", "grape"}

1.6 function
function factorial1(n)
    if n == 0 then
         return 1
    else
         return  n* factorial1(n-1)
    end
end

print(factorial1(5))
factorial2 = factorial1
print(factorial2(5))

function 可以以匿名函数的方式传递参数
function testFun(tab,fun)
    for k, v in pairs(tab) do
        print(fun(k,v));
    end
end

tab={key1="val1",key2="val2"};
testFun(tab,
function(key,val)--匿名函数
    return key.."="..val;
end
);

2.  lua 变量
2.1 变量在使用前,必须在代码中进行声明,即创建改变量
a = 5 --全局变量
local b = 5 --局部变量

function joke()
    c = 5
    local d = 6
end

2.2 赋值变量
a = "hello" .. "world"
t.n = t.n + 1

多个变量同事赋值
a, b = 10, 2*x

交换变量的值
x, y = y, x
a[i], a[j] = a[j], a[i]


3. 循环
3.1 while循环
while(condition)
do
    statements
end

eg1,
a = 10
while(a < 20)
do
    print("a的值为:", a)
    a = a+1
end


3.2 for 循环
for循环分为数值for循环和泛型for循环
3.2.1 数值for循环
for var=exp1,exp2,exp3 do
    <执行体>
end

for i=1,f(x) do
    print(i)
end

for i=10,1,-1 do
    print(i)
end


3.2.2 泛型for循环
for i,v in ipairs(a) do
    print(v)
end

在lua中pairs与ipairs两个迭代器的用法相近,但有一点是不一样的:
pairs可以遍历表中所有的key,并且除了迭代器本身以及遍历表本身还可以返回nil;
但是ipairs则不能返回nil,只能返回数字0,如果遇到nil则退出。它只能遍历到表中出现的第一个不是整数的key


















 



2017年12月13日星期三

正则表达式,python re包

一.正则表达式

1.正则表达式是什么?
正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")。
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串

2.为什么使用正则表达式
 1. 测试字符串模式(可以测试输入字符串,已查看字符串内是否出现电话号码模式或信用卡号码模式,称为数据验证)
 2. 替换文本(可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换)
 3.基于模式匹配从字符串中提取子字符串

3. 正则表达式语法
1. +   匹配 runoob、runooob、runoooooob
2. × 


二.Python正则表达式 

1. Python中的正则表达式
python自1.5版本增加了re模块,它提供了Perl风格的正则表达式模式
re模块使Python拥有全部的正则表达式功能

2.Re的函数介绍

  2.1 匹配功能
1.re.match(pattern, string, flags=0)   匹配成功返回匹配对象,否则返回None

eg1.
#!/usr/bin/python 
 # -*- coding: UTF-8 -*-  
import re  
print(re.match('www', 'www.runoob.com').span()) # 在起始位置匹配 print(re.match('com', 'www.runoob.com'))               # 不在起始位置匹配
运行结果:
(0, 3)
None

eg2.
#!/usr/bin/python  
import re 
line = "Cats are smarter than dogs"  
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I) 
if matchObj:  
print "matchObj.group() : ", matchObj.group() 
print "matchObj.group(1) : ", matchObj.group(1) 
print "matchObj.group(2) : ", matchObj.group(2)  
else:  
print "No match!!"





 运行结果:

matchObj.group() :  Cats are smarter than dogs
matchObj.group(1) :  Cats
matchObj.group(2) :  smarter
 
 
 
2. re.search(pattern, string, flags=0)


#!/usr/bin/python  
# -*- coding: UTF-8 -*-  
import re  
print(re.search('www', 'www.runoob.com').span())   # 在起始位置匹配 print(re.search('com', 'www.runoob.com').span())     # 不在起始位置匹配

运行结果:

(0, 3)
(11, 14)
 
 
3.re.search和re.match的区别

re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。










  2.2 检索和替换
Python的re模块提供了re.sub用于替换字符串中的匹配项
re.sub(pattern, rep1, string, count=0, flags=0)





参考
【1】http://www.runoob.com/regexp/regexp-intro.html


2017年12月3日星期日

2017年11月28日星期二

bazel 初入门学习

 笔者根据bazel官网的c++例程进行学习

1. 安装bazel
安装链接:https://docs.bazel.build/versions/master/install.html

2. 下载仓库:
 git clone https://github.com/bazelbuild/examples/
 例子代码在examples/cpp-tutorial目录下,目录结构为:

examples
└── cpp-tutorial
    ├──stage1
    │  └── main
    │      ├── BUILD
    │      ├── hello-world.cc
    │  └── WORKSPACE
    ├──stage2
    │  ├── main
    │  │   ├── BUILD
    │  │   ├── hello-world.cc
    │  │   ├── hello-greet.cc
    │  │   ├── hello-greet.h
    │  └── WORKSPACE
    └──stage3
       ├── main
       │   ├── BUILD
       │   ├── hello-world.cc
       │   ├── hello-greet.cc
       │   └── hello-greet.h
       ├── lib
       │   ├── BUILD
       │   ├── hello-time.cc
       │   └── hello-time.h
       └── WORKSPACE
如您所见,有三组文件,每组代表本教程中的一个阶段。 在第一阶段,你将建立一个单一的目标驻留在一个包中。 在第二阶段,你将把你的项目分成多个目标,但是把它保存在一个包里。 在第三个也是最后一个阶段,你将把你的项目分成多个包,并用多个目标构建它。

3. Build
3.1 set up the workspace
在构建项目之前,您需要设置其工作区(workspace)。 工作区是保存项目源文件和Bazel构建输出的目录。 它还包含了Bazel认为特殊的文件:
  (1)WORKSPACE文件,它将目录及其内容标识为Bazel工作区,并位于项目目录结构的根目录下
   (2) 一个或多个BUILD文件,告诉Bazel如何构建项目的不同部分。 (包含BUILD文件的工作空间中的一个目录就是一个包,在本教程的后面,您将学习有关包的信息。)
要将目录指定为Bazel工作区,请在工程目录中创建一个名为WORKSPACE的空文件。当Bazel构建项目时,所有输入和依赖项必须位于同一个WORKSPACE中。

3.2 ubderstand the BUILD file
 BUILD文件包含几种不同类型的Bazel指令。 最重要的类型是构建规则,它告诉Bazel如何构建所需的输出,如可执行的二进制文件或库。 BUILD文件中每个构建规则的实例称为目标,并指向一组特定的源文件和依赖关系。 目标也可以指向其他目标。
 看下根据上述git命令clone下来的 examples/cpp-tutorial/stage1/main 目录

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
)
 在我们的例子中,hello-world目标实例化了Bazel的内置cc_binary规则。 该规则告诉Bazel从hello-world.cc源文件中构建一个自包含的可执行二进制文件hello-world,并且不包含任何依赖.

3.3 Build the project
让我们来构建示例项目,转到cpp-tutorial/stage1目录下并且运行下面的命令:
bazel build //main:hello-world
注意目标标签 - // 表示WORKSPACE所在的根目录,hello-world是我们在BUILD文件中命名的目标。

INFO: Found 1 target...
Target //main:hello-world up-to-date:
  bazel-bin/main/hello-world
INFO: Elapsed time: 2.267s, Critical Path: 0.25s
 恭喜你,你刚刚建立了你的第一个Bazel目标! Bazel将构建输出放置在工作空间根部的bazel-bin目录中。 通过浏览其内容来了解Bazel的输出结构。
 现在可以测试你刚刚编译的代码了
   bazel-bin/main/hello-world

3.4 Review the dependency graph
一个成功的构建具有在BUILD文件中明确声明的所有依赖关系。 Bazel使用这些BUILD文件来创建项目的依赖关系图,从而实现准确的增量构建.
 让我们来看看我们的示例项目的依赖关系。 首先,生成依赖关系图的文本表示(在工作空间根目录下运行该命令):
bazel query --nohost_deps --noimplicit_deps 'deps(//main:hello-world)' \
  --output graph
将运行结果输入 webgraphviz
结果如下:























现在你已经建立了你的工作空间,建立了你的项目,并且检查了它的依赖关系,让我们增加做一些更复杂的事情。

Refine your bazel build
虽然单个目标对于小型项目已经足够了,但是对于较大的项目,您可能需要拆分为多个目标和包,以允许快速增量构建(即只重建已更改的内容),并通过构建项目的多个部分来加速构建
在cpp-tutorial/stage2/main文件中
 BUILD文件内容为:

cc_library(
    name = "hello-greet",
    srcs = ["hello-greet.cc"],
    hdrs = ["hello-greet.h"],
)

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
    deps = [
        ":hello-greet",
    ],
)
deps表示依赖于,hdrs表示头文件?
运行bazel build //main:hello-world,结果如下:
INFO: Found 1 target...
Target //main:hello-world up-to-date:
  bazel-bin/main/hello-world
INFO: Elapsed time: 2.399s, Critical Path: 0.30s
现在可以运行bazel-bin/main/hello-world进行测试
依赖图如下:

 











Use multiple packages
如下目录cpp-tutorial/stage3
└──stage3
   ├── main
   │   ├── BUILD
   │   ├── hello-world.cc
   │   ├── hello-greet.cc
   │   └── hello-greet.h
   ├── lib
   │   ├── BUILD
   │   ├── hello-time.cc
   │   └── hello-time.h
   └── WORKSPACE

BUILD文件如下:
lib/BUILD:
cc_library(
    name = "hello-time",
    srcs = ["hello-time.cc"],
    hdrs = ["hello-time.h"],
    visibility = ["//main:__pkg__"],
)
main/BUILD :
cc_library(
    name = "hello-greet",
    srcs = ["hello-greet.cc"],
    hdrs = ["hello-greet.h"],
)

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
    deps = [
        ":hello-greet",
        "//lib:hello-time",
    ],
) 
 
依赖图如下:
 
 
 
 
 
 
 
 
 
 
 
 
看完这个,你可以开始系统的学习

2017年11月22日星期三

pycharm 快捷键

快捷键: https://segmentfault.com/a/1190000005776418

我的逐步积累:
shift + F6 全局修改一个函数名或者变量名等

Ctrl + R     替换
Ctrl + Shift + F  全局查找
Ctrl + Shift + R  全局替换

tensorflow错误集

1. restore from checkpoint
    1.1 tensorflow.python.framework.errors_impl.InternalError: Unable to get element from the feed as bytes    此处表明文件目录不对

    1.2 export model 时出现:NotFoundError (see above for traceback): Key Modeffl/eval_net/l1/b1 not found in checkpoint
     [[Node: save/RestoreV2 = RestoreV2[dtypes=[DT_FLOAT], _device="/job:localhost/replica:0/task:0/cpu:0"](_arg_save/Const_0_0, save/RestoreV2/tensor_names, save/RestoreV2/shape_and_slices)]]
  在新建模型的时候在前面加上了name_scape和variable_scope,导致检查点文件里参数的名称和新建模型的名称不一致,故而不可恢复,因为在检查点文件中找不到对应的参数名称
故而,如果在train模型时前面加上了相应的name_scope或者variable_scope,那么在导出时候也要加上,以此保证参数名称的一致性

2. serving

    2.1  Invalid argument: Shape [?,62] is not fully defined

找到一个解决方案,但是不适合我,我用的是官网的方法
https://stackoverflow.com/questions/41346058/you-must-feed-a-value-for-placeholder-tensor-input-example-tensor-with-dtype-s 

我遇到这个问题是在export,serving和client的过程中.
花了整整一天 ,终于知道是什么错了.
原因是在模型中我们用的是placeholder为了接收输入的组件,在export的时候,我们存储模型的参数和规定模型的输入和输出.但是由于模型中的placeholder实际上并没有与export的输入产生关联,故而出错.所以会一直报shape[?,62] is not fully defined.
要解决这个问题.就需要知道如何讲s与export的inputs产生关联

发现是这个问题后,就很好解决了.
 (1).当模型的输入是作为参数时,在外部定义placeholder,然后指定模型参数为placeholder的值,关联了模型的输入与export定义的输入
 (2).当模型的输入是placeholder时,就需要直接将input指定为model.[输入placeholder名就行了]

2017年11月19日星期日

论文开题需要做的事情

持续更新

11月20-11月30

第一件事: 看各大知名workshop现如今的研究方向,对论文的研究方向有个大致的了解

第二件事: 确定是基于工程方向的文章,找往届的论文看看格式

12月1-12月30

第三件事:论文题目初定,有细节的地方尚待考量

dan,ddqn,duel dqn
https://blog.csdn.net/u013236946/article/details/73161586

2017年11月8日星期三

那些年,我看过的优秀代码

介于看代码很重要,从今天开始看代码:

1. github : tensorflow/nmt     仓库[https://github.com/tensorflow/nmt.git]
 主题:机器翻译
 网络:rnn,bi-rnn,deep n
 时间:
2017年11月20日 : 看完程序脉络和train过程

学到的东西
1.
import argparse
#创建一个命令解析器的句柄

parser = argparse.ArgumentParser()
#注册一个命令解析器参数类型,其中lambda v: v.lower()=="true"
#是代表一个匿名函数的实现,主要判断获取到的参数v转换成小写后是否等于true
parser.register("type", "bool", lambda v: v.lower() == "true")

2.add_argument里面参数的含义
http://blog.csdn.net/u013177568/article/details/62432761


在一月份结束时务必完成!  江山代有人才出,各领风骚数百年啊啊啊啊!
 (差不多看完2018/01/23)


2. Surprise     仓库【https://github.com/NicolasHug/Surprise.git】    主页【http://surpriselib.com/

 (差不多看完2018/01/25 ,做小组汇报)


3. KubeFlow  仓库【https://github.com/google/kubeflow】

2.flask[据说非常适合工程上的学习]

 

2017年11月6日星期一

2017年10月31日星期二

lstm多层代码分析

觉得很好,记录一下,帮助我解决了不少困惑。
链接在此

查找关键字:
tensorflow lstm cell实现rnn

2017年10月27日星期五

linux,vim及.bashrc

1.关于.bashrc的加载
加载过程

2.linux 参考
2.1 处理目录常用命令
ls:列出目录
cd:切换目录
pwd:显示目前的目录
mkdir:创建一个新的目录
rmdir:删除一个空的目录
cp:复制文件或目录
rm:移除文件或目录
mv:移动文件

2.2 文件内容查看
cat:由第一行开始显示文件内容
tac:从最后一行开始显示文件内容
nl:显示的时候,顺道输出行号
more:一页一页的显示
less:一页一页的显示,可前后翻页
head:只看前几行
tail:只看后几行
可使用man [命令]来查看帮助文档

eg: head -10 tmp.txt > tmp1.txt 拷贝文件前几行到另一个文件

2.3 磁盘管理
df -h 显示磁盘容量
top 查看电脑内存,cpu占用量

2.4 进程相关
ps -ef |grep
lsof -i:[port]

2.5 网络传输
scp,nc(仅限局域网传输,速度非常快)

3.vim的三个模式
命令模式,插入模式和底线命令模式
命令模式:刚刚启动vim
插入模式:按i
底线插入模式:wq

3.1 vim常用按键模式

移动光标的方法:(我觉得应该记得的部分)

h 或 左箭头  光标向左移动一个字符
j  或 下箭头   光标向下移动一个字符
k 或 上箭头   光标向上移动一个字符
l  或 右箭头   光标向右移动一个字符
如果想要连续移动很多行,用如30j的组合方式
ctrl + f  屏幕向下移动一页,相当于 【page down】
ctrl + b 屏幕向上移动一页,相当于【page up]
ctrl + d 屏幕向下移动半页
ctrl + u 屏幕向上移动半页

0或者home 移到句子的最前面
end  移动到句子的最后面

n<space> 向前移动n个字符
nG n为数字,移动到这个档案的第n行
gg 移动到这个文件的第一行 【常用】
shift + g 移动到文件最后一行,常用
$ 移动至行尾
^ 移动至行首

 搜索替换:
 /word 向光标之下寻找一个名称为word的字符串。
?word 向光标之上寻找一个字符串名称为word的字符串
n 重复上一次的动作,向下搜索,与/word和?word一起使用非常的靠谱
N 与n相反,进行前向搜索
:n1,n2s/word1/word2/g  在第n1与n2之间寻找word1这个字符串,并将该字符串取代为word2
:%s/word1/word2/g    与上面相同
:1,$s/word1/word2/gc  在第一行到最后一行寻找word1这个字符串,并将改字符串取代为word2

删除,复制与粘贴
x,X    在一行中,x为向后删除一个字符,X为向前删除一个字符
nx      n为数字,连续向后删除n个字符
dd      删除游标所在的那一整行
ndd    n为数字,删除光标所在向下n行
yy       复制游标所在处,到该行的最前面一个字符
nyy     复制光标所在的向下n行
p,P      p为将已复制的数据在光标的下一行粘贴,P为贴在游标上一行
u         复原前一个动作
ctrl + r 重做上一个动作

上面两个动作相当于撤销和复原


一般模式切换到编辑模式的可用按钮说明
i,I    进入插入模式,i是从目前所在处插入,I为在目前所在行的第一个非空格处开始插入
a,A  进入插入模式,a为从目前光标所在的下一个字符处开始插入,A为从光标所在行的最后一个字符处开始插入
o,O  进入插入模式,o为在目前光标所在的下一行出插入新的一行,O为在目前光标所在处的上一行插入新的一行
r,R   进入插入模式
Esc  退出编辑模式,回到一般模式中


一般模式切换到指令行模式的可用的按钮说明
:w    将编辑的数据写入硬盘档案中
:w!   强制写入硬盘档案
:q     离开vim
:q!    修改又不想保存,表示强制离开不存储档案

:wq  存储后离开,
:wq! 强制存储并退去

多行注释和多行取消注释
1.多行注释
先按Esc  ->  ctrl+v   -> I  ->  [输入你想输入的字符:如(# )]   ->  再按Esc

2.多行取消注释

ESC
Ctrl+v键进入列编辑模式
上下键选中
d键删除











     

2017年10月26日星期四

tensorflow-serving,grpc,bazel学习

1.最近遇到一个问题,在应用tensorflow serving机制的时候,运行代码时,原本1s可以得到结果的程序在用了clinet从serving端读取慢了5倍左右。

从网上查了一下,发现是tensorflow-model-serving的安装出了问题,其安装有两种方式,一种是install using apt-get方式,一种是install from source,如果使用apt-get方式安装,则不会出什么问题,但是如果使用source方式安装,可按照链接提供的方法修改bazel 的编译方式,就会一切正常,具体原理并不清楚。
https://github.com/tensorflow/serving/issues/456


2. grpc学习

2017年10月24日星期二

论文搜索技能get

1.各大有名的workshop【语音方面】:
  workshop详见 链接
  这些workshop上通常收集了一些最有知名度的各个领域相关的文章,通常还会有整理好的ppt,读这些ppt,就可以从中找到你所关注领域的文章
【但是由于workshop每年开一次,所以通常2017年你能看到的就是2016年的文章】

2.arxiv网站 
由于论文是有审核期的,这个时候如果有人发了跟你一样的论文,就会发生重复,所以,发论文的人为了不让别人的论文面世时间位于别人后面,在审核期就会把文章发到arxiv上,所以,你可以从上面搜索最新的文章。

3.找好的文章,一定要看团队和作者或者发表在哪里
当然,从一篇好的文章中,它所引用的文章也会相应的有质量,可以选择性的挑选着看

4.关键字选择
当你在google或者arxiv上搜索文章时,如dialog state tracker,在学术上通常还有其他的表示,比如dialog有的或表示成dialogue,tracker被表示成tracking.要多换几个关键词进行搜索。有时候直接搜缩写也可能会有用。

2017年10月18日星期三

n-gram算法

初理解:
http://blog.csdn.net/ahmanz/article/details/51273500

具体公式:
http://blog.sina.com.cn/s/blog_4b2ddd15010151th.html

discriminative model(判别模型) 和 Generative Model(生成模型)


  • 判别模型Discriminative Model,又可以称为条件模型,或条件概率模型。估计的是条件概率分布(conditional distribution), p(class|context)。
  • 生成模型Generative Model,又叫产生式模型。估计的是联合概率分布(joint probability distribution),p(class, context)=p(class|context)*p(context)。
  •  
  • 看了下面这篇,终于有点懂了:
  • 链接

2017年10月9日星期一

tensorboard 不报错也不显示

笔者运行tensorboard --logdir=saver[此处填log文件位置]

出现一下结果:
Starting TensorBoard 55 at http://aisp:6006
(Press CTRL+C to quit)
WARNING:tensorflow:Found more than one graph event per run, or there was a metagraph containing a graph_def, as well as one or more graph events.  Overwriting the graph with the newest event.
WARNING:tensorflow:Found more than one metagraph event per run. Overwriting the metagraph with the newest event.




打开链接http://aisp:6006,没有结果显示,搜索未果
发现tensorboard的兼容浏览器是google chrome,下载即可运行

2017年9月28日星期四

ubuntu 终端操作相关

改变文件夹相关权限: sudo chmod 0775 * [*代表文件夹]

进程相关

相关知识点
1.僵尸进程和孤儿进程:
http://www.cnblogs.com/limt/p/4199255.html

相关操作
1. ps -ef  显示全部进程和信息

2017年9月27日星期三

git常用操作

git操作分为两大类,一种是处理文件的操作;另一种是分支操作。下面总结一下git常用操作:

一.文件处理操作
0.对比前后差别:           git diff    通常改完代码后需要查看修改是否正确
1.添加文件到缓存区:    git add           [git add .默认添加所有文件到缓存区]
2.添加文件到本地仓库: git commit -m "[修改×××]"
3.提交文件到远程仓库: git push origin [本地分支名]:[远程分支名]    如果名称相同可以省略

上述是正常流程下的提交操作,但是如果在提交中操作,或者添加或提交了本来不应该提交的代码,可以进行一下操作:
 4.撤销add的文件:        git reset HEAD .  [撤销添加的所有文件]
                                      git reset HEAD -filename [撤销指定文件]
 5.撤销commit的文件:  git log  [查看commit的日志]
                                      git reset --hard commit_id [撤销commit_id次的commit]
 6.撤销push的文件:       git reset --hard <版本号> [如果不加版本号则回退到之前的一次]

 7. 下拉远程分支上的代码 git pull origin [远程分支名]

二.分支操作
1.创建本地分支    git checkout -b [分支名] [创建一个空分支]
                           git checkout -b [分支名] origin/[远程分支名] [拉远程分支下的代码]
2.创建远程分支    git push origin [本地分支名]:[远程分支名]

3.删除本地分支    git branch -D [本地分支名]
4.删除远程分支    git push origin :[要删除的远程分支名]    [推空白的代码上去,就是删除]

5.切换分支           git checkout [分支名]

6.查看远程分支    git branch -r

7.查看某一历史分支    git log 查询分支的提交编码,如 123456...89
                                  git checkout 123456..89 [转到具体分支]

后续有的话在补充

2017年9月25日星期一

virtualenv虚拟环境及zmq安装

特别6的虚拟环境安装教程:
http://snailvfx.github.io/2016/05/11/virtualenv/


zmq安装教程:
https://tuananh.org/2015/06/16/how-to-install-zeromq-on-ubuntu/

zmq教程
https://www.zhihu.com/question/28648575

pip下镜像源配置

参考http://www.jianshu.com/p/785bb1f4700d

临时使用:
pip install pythonModuleName -i https://pypi.douban.com/simple

修改~/.pip/pip.conf:
[global]
index-url = [https://pypi.douban.com/simple你想使用的镜像]

镜像详细参考:
http://blog.csdn.net/d5224/article/details/52025897

安装openfst,pyfst

首先安装openfst,如果你想继续安装pyfst的话,你需要安装openfst1.3.3的版本,因为pyfst始终不跟新,只支持到openfst1.3.3
打开openfst主页,下载1.3.3的版本http://www.openfst.org/twiki/bin/view/FST/FstDownload

解压文件,运行
 ./configure
make
sudo make install
安装成功

 通过这里测试是否成功:http://blog.csdn.net/chinabing/article/details/50724575
如果编译失败,通过https://github.com/vchahun/fast_umorph/issues/1来修改interval-set.h文件

openfst需要c++11,安装链接如下:
http://blog.csdn.net/lisonglisonglisong/article/details/21947255

在~/.bashrc中添加:
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib
到此,openfst差不多安装好了

接下来安装pyfst
sudo CFLAGS="-std=c++0x" pip install pyfst -i https://pypi.douban.com/simple
值得注意的是,镜像一定要用doubian的,因为pyfst一直没有更新,很多镜像已经没有pyfst的包了。
如果你看的时候,发现用豆瓣的镜像也会出现问题,请试用如下链接的镜像:
http://blog.csdn.net/d5224/article/details/52025897


github clone指定版本的文件

先找到git上指定的仓库
点击release,查看指定版本
用git clone [**.git]  -b [v*版本号]来下载指定版本

2017年9月13日星期三

文件读取指针偏移 seek()

文件读取时改变文件读取指针的位置
seek(len_of_character,0) 0表示从文件开头开始,len_of_character表示需要移动的字节数

当0的位置变为1,表示相对于当前位置,目前感觉并不好用

2017年9月12日星期二

epoch,batch,num_steps

一个epoch通常表示在训练集上的一次迭代。举个列子,如果你有20000张图像并且batch_size=100,那么这个epoch包含20000/100 = 200个steps.

tensorflow/models/ptb

ptb的代码可以详见gitlab上的tensorflow/models/tutorials下,本文只详解他的数据前处理和模型部分。

1.运行
首先说一下他的运行 ,下载数据集:http://www.fit.vutbr.cz/~imikolov/rnnlm/simple-examples.tgz
解压出ptb.test/train/valid.txt文件,
运行命令行 :python ptb_word_lm.py --data_path=【文件存放目录】 --model small即可运行成功
2.数据前处理部分
读代码首先要找到主函数,在ptb_word_lm.py文件中,我们看到main函数


def main(_):
  if not FLAGS.data_path:
    raise ValueError("Must set --data_path to PTB data directory")
  gpus = [
      x.name for x in device_lib.list_local_devices() if x.device_type == "GPU"  ]
  if FLAGS.num_gpus > len(gpus):
    raise ValueError(
        "Your machine has only %d gpus "        "which is less than the requested --num_gpus=%d."        % (len(gpus), FLAGS.num_gpus))

  raw_data = reader.ptb_raw_data(FLAGS.data_path)
  train_data, valid_data, test_data, _ = raw_data
  
显然,与前处理相关的只有ptb_raw_data()函数,在reader文件中,找到相关的四个函数:

import tensorflow as tf


def _read_words(filename):
  with tf.gfile.GFile(filename, "r") as f:
    return f.read().decode("utf-8").replace("\n", "<eos>").split()


def _build_vocab(filename):
  data = _read_words(filename)
  counter = collections.Counter(data)
  count_pairs = sorted(counter.items(), key=lambda x: (-x[1], x[0]))
  words, _ = list(zip(*count_pairs))
  word_to_id = dict(zip(words, range(len(words))))
  return word_to_id


def _file_to_word_ids(filename, word_to_id):
  data = _read_words(filename)
  return [word_to_id[word] for word in data if word in word_to_id]


def ptb_raw_data(data_path=None):

  train_path = os.path.join(data_path, "ptb.train.txt")
  valid_path = os.path.join(data_path, "ptb.valid.txt")
  test_path = os.path.join(data_path, "ptb.test.txt")

  word_to_id = _build_vocab(train_path)
  train_data = _file_to_word_ids(train_path, word_to_id)
  valid_data = _file_to_word_ids(valid_path, word_to_id)
  test_data = _file_to_word_ids(test_path, word_to_id)
  vocabulary = len(word_to_id)
  return train_data, valid_data, test_data, vocabulary
_build_vocab函数首先读入文件中所有数据(如:the,a,...),然后以每个单词作为键值,对应给其一个整形数值('the':32021,'a':323),count_pairs将其转化为对应的元组('the',32021),('a',323),建立词表
_file_to_word_ids函数讲文件转化为此表中词所对应的整形数据
返回对应的训练集,验证集和测试集对应的整形数据文件和词表对应长度。

with tf.Graph().as_default():
  initializer = tf.random_uniform_initializer(-config.init_scale,                                              config.init_scale)

  with tf.name_scope("Train"):
    train_input = PTBInput(config=config, data=train_data, name="TrainInput")
    with tf.variable_scope("Model", reuse=None, initializer=initializer):
      m = PTBModel(is_training=True, config=config, input_=train_input)
    tf.summary.scalar("Training Loss", m.cost)
    tf.summary.scalar("Learning Rate", m.lr)
现在跳回ptb_word_lm,在主函数中建立模型,模型的输入函数为PTBInput(),故转去其定义查看
def ptb_producer(raw_data, batch_size, num_steps, name=None):
  """Iterate on the raw PTB data.
  This chunks up raw_data into batches of examples and returns Tensors that  are drawn from these batches.
  Args:    raw_data: one of the raw data outputs from ptb_raw_data.    batch_size: int, the batch size.    num_steps: int, the number of unrolls.    name: the name of this operation (optional).
  Returns:    A pair of Tensors, each shaped [batch_size, num_steps]. The second element    of the tuple is the same data time-shifted to the right by one.
  Raises:    tf.errors.InvalidArgumentError: if batch_size or num_steps are too high.  """  with tf.name_scope(name, "PTBProducer", [raw_data, batch_size, num_steps]):
    raw_data = tf.convert_to_tensor(raw_data, name="raw_data", dtype=tf.int32)

    data_len = tf.size(raw_data)
    batch_len = data_len // batch_size
    data = tf.reshape(raw_data[0: batch_size * batch_len],                      [batch_size, batch_len])

    epoch_size = (batch_len - 1) // num_steps
    assertion = tf.assert_positive(
        epoch_size,        message="epoch_size == 0, decrease batch_size or num_steps")
    with tf.control_dependencies([assertion]):
      epoch_size = tf.identity(epoch_size, name="epoch_size")

    i = tf.train.range_input_producer(epoch_size, shuffle=False).dequeue()
    x = tf.strided_slice(data, [0, i * num_steps],                         [batch_size, (i + 1) * num_steps])
    x.set_shape([batch_size, num_steps])
    y = tf.strided_slice(data, [0, i * num_steps + 1],                         [batch_size, (i + 1) * num_steps + 1])
    y.set_shape([batch_size, num_steps])
    return x, y
可以很容易看出,其是每次读出一个batch*num_steos的数据。

3.模型部分
当我们看完数据的前处理部分,那么重点就来了,那就是数据的model部分
class PTBModel(object):
  """The PTB model."""
  def __init__(self, is_training, config, input_):
    self._is_training = is_training
    self._input = input_
    self._rnn_params = None    self._cell = None    self.batch_size = input_.batch_size
    self.num_steps = input_.num_steps
    size = config.hidden_size
    vocab_size = config.vocab_size

    with tf.device("/cpu:0"):
      embedding = tf.get_variable(
          "embedding", [vocab_size, size], dtype=data_type())
      inputs = tf.nn.embedding_lookup(embedding, input_.input_data)
    if is_training and config.keep_prob < 1:
      inputs = tf.nn.dropout(inputs, config.keep_prob)

    output, state = self._build_rnn_graph(inputs, config, is_training)

    softmax_w = tf.get_variable(
        "softmax_w", [size, vocab_size], dtype=data_type())
    softmax_b = tf.get_variable("softmax_b", [vocab_size], dtype=data_type())
    logits = tf.nn.xw_plus_b(output, softmax_w, softmax_b)
     # Reshape logits to be a 3-D tensor for sequence loss    logits = tf.reshape(logits, [self.batch_size, self.num_steps, vocab_size])

    # Use the contrib sequence loss and average over the batches    loss = tf.contrib.seq2seq.sequence_loss(
        logits,        input_.targets,        tf.ones([self.batch_size, self.num_steps], dtype=data_type()),        average_across_timesteps=False,        average_across_batch=True)

    # Update the cost    self._cost = tf.reduce_sum(loss)
    self._final_state = state

    if not is_training:
      return
    self._lr = tf.Variable(0.0, trainable=False)
    tvars = tf.trainable_variables()
    grads, _ = tf.clip_by_global_norm(tf.gradients(self._cost, tvars),                                      config.max_grad_norm)
    optimizer = tf.train.GradientDescentOptimizer(self._lr)
    self._train_op = optimizer.apply_gradients(
        zip(grads, tvars),        global_step=tf.contrib.framework.get_or_create_global_step())

    self._new_lr = tf.placeholder(
        tf.float32, shape=[], name="new_learning_rate")
    self._lr_update = tf.assign(self._lr, self._new_lr)

  def _build_rnn_graph(self, inputs, config, is_training):
    if config.rnn_mode == CUDNN:
      return self._build_rnn_graph_cudnn(inputs, config, is_training)
    else:
      return self._build_rnn_graph_lstm(inputs, config, is_training)

  def _build_rnn_graph_cudnn(self, inputs, config, is_training):
    """Build the inference graph using CUDNN cell."""    inputs = tf.transpose(inputs, [1, 0, 2])
    self._cell = tf.contrib.cudnn_rnn.CudnnLSTM(
        num_layers=config.num_layers,        num_units=config.hidden_size,        input_size=config.hidden_size,        dropout=1 - config.keep_prob if is_training else 0)
    params_size_t = self._cell.params_size()
    self._rnn_params = tf.get_variable(
        "lstm_params",        initializer=tf.random_uniform(
            [params_size_t], -config.init_scale, config.init_scale),        validate_shape=False)
    c = tf.zeros([config.num_layers, self.batch_size, config.hidden_size],                 tf.float32)
    h = tf.zeros([config.num_layers, self.batch_size, config.hidden_size],                 tf.float32)
    self._initial_state = (tf.contrib.rnn.LSTMStateTuple(h=h, c=c),)
    outputs, h, c = self._cell(inputs, h, c, self._rnn_params, is_training)
    outputs = tf.transpose(outputs, [1, 0, 2])
    outputs = tf.reshape(outputs, [-1, config.hidden_size])
    return outputs, (tf.contrib.rnn.LSTMStateTuple(h=h, c=c),)

  def _get_lstm_cell(self, config, is_training):
    if config.rnn_mode == BASIC:
      return tf.contrib.rnn.BasicLSTMCell(
          config.hidden_size, forget_bias=0.0, state_is_tuple=True,          reuse=not is_training)
    if config.rnn_mode == BLOCK:
      return tf.contrib.rnn.LSTMBlockCell(
          config.hidden_size, forget_bias=0.0)
    raise ValueError("rnn_mode %s not supported" % config.rnn_mode)

  def _build_rnn_graph_lstm(self, inputs, config, is_training):
    """Build the inference graph using canonical LSTM cells."""    # Slightly better results can be obtained with forget gate biases    # initialized to 1 but the hyperparameters of the model would need to be    # different than reported in the paper.    cell = self._get_lstm_cell(config, is_training)
    if is_training and config.keep_prob < 1:
      cell = tf.contrib.rnn.DropoutWrapper(
          cell, output_keep_prob=config.keep_prob)

    cell = tf.contrib.rnn.MultiRNNCell(
        [cell for _ in range(config.num_layers)], state_is_tuple=True)

    self._initial_state = cell.zero_state(config.batch_size, data_type())
    state = self._initial_state
    # Simplified version of tensorflow_models/tutorials/rnn/rnn.py's rnn().    # This builds an unrolled LSTM for tutorial purposes only.    # In general, use the rnn() or state_saving_rnn() from rnn.py.    #    # The alternative version of the code below is:    #    # inputs = tf.unstack(inputs, num=num_steps, axis=1)    # outputs, state = tf.contrib.rnn.static_rnn(cell, inputs,    #                            initial_state=self._initial_state)    outputs = []
    with tf.variable_scope("RNN"):
      for time_step in range(self.num_steps):
        if time_step > 0: tf.get_variable_scope().reuse_variables()
        (cell_output, state) = cell(inputs[:, time_step, :], state)
        outputs.append(cell_output)
    output = tf.reshape(tf.concat(outputs, 1), [-1, config.hidden_size])
    return output, state

  def assign_lr(self, session, lr_value):
    session.run(self._lr_update, feed_dict={self._new_lr: lr_value})

  def export_ops(self, name):
    """Exports ops to collections."""    self._name = name
    ops = {util.with_prefix(self._name, "cost"): self._cost}
    if self._is_training:
      ops.update(lr=self._lr, new_lr=self._new_lr, lr_update=self._lr_update)
      if self._rnn_params:
        ops.update(rnn_params=self._rnn_params)
    for name, op in ops.iteritems():
      tf.add_to_collection(name, op)
    self._initial_state_name = util.with_prefix(self._name, "initial")
    self._final_state_name = util.with_prefix(self._name, "final")
    util.export_state_tuples(self._initial_state, self._initial_state_name)
    util.export_state_tuples(self._final_state, self._final_state_name)

  def import_ops(self):
    """Imports ops from collections."""    if self._is_training:
      self._train_op = tf.get_collection_ref("train_op")[0]
      self._lr = tf.get_collection_ref("lr")[0]
      self._new_lr = tf.get_collection_ref("new_lr")[0]
      self._lr_update = tf.get_collection_ref("lr_update")[0]
      rnn_params = tf.get_collection_ref("rnn_params")
      if self._cell and rnn_params:
        params_saveable = tf.contrib.cudnn_rnn.RNNParamsSaveable(
            self._cell,            self._cell.params_to_canonical,            self._cell.canonical_to_params,            rnn_params,            base_variable_scope="Model/RNN")
        tf.add_to_collection(tf.GraphKeys.SAVEABLE_OBJECTS, params_saveable)
    self._cost = tf.get_collection_ref(util.with_prefix(self._name, "cost"))[0]
    num_replicas = FLAGS.num_gpus if self._name == "Train" else 1    self._initial_state = util.import_state_tuples(
        self._initial_state, self._initial_state_name, num_replicas)
    self._final_state = util.import_state_tuples(
        self._final_state, self._final_state_name, num_replicas)

daixu

2017年8月24日星期四

tensorflow serving-serving a tensorflow model

(学习使用,仅供参考) 详细请参考:https://www.tensorflow.org/serving/serving_basic
这章教你怎样使用tf serving export出一个已经训练好的模型,并使用标准的tensorflow_model_server 将其服务出去。

这章需要两部分代码:
  a python file:mnist_saverd_model.py,它用来训练和导出模型
  一个modelsever二进制文件,这个modelserver可以找到新导出的模型并调用gRpc服务将其服务出去。

1.Train and Export tf Model
你可以在mnist_saverd_model.py中看到,训练部分和MNIST For ML Beginners tutorial中的相同,tf graph在sess中开始运行,其输入为x(input tensor[image]),其输出为y(output tensor[softmax score])

 然后我们使用SavedModelBuilder module去export模型,SavedModelBuilder保存一个训练过模型的“snapshot”,以便在预测的时候可以被load。

from tensorflow.python.saved_model import builder as saved_model_builder
...
export_path_base = sys.argv[-1]
export_path = os.path.join(
      compat.as_bytes(export_path_base),
      compat.as_bytes(str(FLAGS.model_version)))
print 'Exporting trained model to', export_path
builder = saved_model_builder.SavedModelBuilder(export_path)
builder.add_meta_graph_and_variables(
      sess, [tag_constants.SERVING],
      signature_def_map={
           'predict_images':
               prediction_signature,
           signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
               classification_signature,
      },
      legacy_init_op=legacy_init_op)
builder.save()

SavedModelBuilder.__init__需要下面的参数:
 1.export_path 导出的路径
SavedModelBuilder在没有目录的时候创建目录,在这个例子中,拼接了命令行参数和model_version得到真正的导出目录,FLAGS.model_version指定的模型的版本,下一次导出的版本一定要比上次导出的版本版本号大,每个版本的模型都被导出到同一指定目录下的不同子目录。

你可以使用builder添加子图和变量,用SavedModelBuilder.add_meta_graph_and_variables(),其具有以下参数:
 1.sess 是一个tf session,它包含你导出的训练模型
 2.tags 是一系列的tags,它们用来保存子图,在这个例子里,因为我们想在serving中使用图,我们使用已经在SavedModel tag 常量中定义好的serve tag.
  3.signature_def_map指定 。。。,Signature 指定什么类型的模型将会被导出,并指定预测时的input/output

signature_def_map中的serving_default指定默认的serving signature,默认的serving signature def key,和其他的与signature相关的常量一起,被定义为SavedModel signature常量。

如果你想更容易的build signature defs







2017年8月23日星期三

tensorflow serving-architecture overviw

(学习所需,仅供参考)
TensorFlow服务是一个灵活的,高性能的机器学习模型的服务系统,专为生产环境而设计。 他可以轻松部署新的算法和实验,同时保持相同的服务器体系结构和API。 TensorFlow服务提供与型号的即时集成,但可以轻松扩展到其他类型的型号。

1.关键概念
你首先应该知道下面几个关键的概念。

1.1 Servables
Servables是TF Serving的关键抽象。 Servables是客户端计算图时的隐藏对象。一个Servable的大小和颗粒是灵活的,一个Servable可以包含从单个表到单个模型或者多个模型的所有东西,Servables可以有任意类型和种类的接口,使其能够足够敏捷和扩展:
  streaming results/experimental APIs/asynchronous modes of operation
Servables不管理自己的生命周期,典型的Servables有以下几种:
  a TensorFlow SavedModelBundle (tensorflow::Session)
  a lookup table for embedding or vocabulary lookups

1.1.1 Servable Versions
 TensorFlow服务可以在单个服务器实例的整个生命周期内处理一个或多个可服务的版本。 这使得新的算法配置,权重和其他数据可以随着时间加载。 版本允许同时加载多个可执行版本,支持逐步推出和实验。 在服务时间,客户可以请求特定型号的最新版本或特定版本号。

1.1.2 Servable Streams
可服务的流是可序列化的序列,按照增加的版本号进行排序。

1.1.3 Models
TensorFlow服务表示一个模型作为一个或多个服务。 机器学习模型可以包括一个或多个算法(包括学习权重)和查找或嵌入表。
您可以将复合模型表示为以下任一项:
     多个独立的服务
     单一复合可服务
可服务的也可以对应于模型的一部分。 例如,可以在许多TensorFlow服务实例中分割大型查找表。

1.1.4 Loaders
Loaders管理servables的生命周期,一个Loader API支持独立于特定学习的算法。具体来说,Loaders标准化了loading和unloading服务的接口。

1.1.5 Sources
Sources are plugin modules that originate servables; each Source originates zero or more servable streams. For each stream, a Source supplies one Loader instance for each version it wants to have loaded. (To be precise, a Source is actually chained together with zero or more SourceAdapters, and the last item in the chain emits Loaders.)

TensorFlow Serving’s interface for Sources is simple and narrow, so it lets you use arbitrary storage systems to discover servables to load. Sources may access other mechanisms such as RPC. TensorFlow Serving includes common reference Source implementations. For example, TensorFlow Serving can poll a file system.

Sources can house state that is shared across multiple servables or versions, for special cases such as models that efficiently accept delta updates.

1.1.6 Aspired Versions
Aspired Versions代表了可以被装载好了的servable版本的集合,Sources通过一个单独的servable流与其沟通,当Source把一个新的列表的版本交给Manager时,它就取代了前面的一个版本,


2.Managers
Managers处理Servables的整个生命周期,包括:
  loading Servables
       serving Servables
       unloading Servables
 Managers监听sources并且追踪所有的版本,Managers尝试去实现Sources的请求,但是在请求资源不存在的时候,Managers会拒绝load aspired version,同时,他也有可能推迟unload.例如:一个Manager可能会等待知道一个更新的版本被load完毕,其政策是确保load的版本一定是最新的版本。

Managers提供一个简单的接口-GetServableHandle(),让客户端去获取loaded的servable实例。

3.Core
TensorFlow Serving Core manages (via standard TensorFlow Serving APIs) the following aspects of servables:
    lifecycle
    metrics
TensorFlow Serving Core treats servables and loaders as opaque objects.

4.Life of a Servable


一般来说:
  1.Sources为Servable版本创建Loaders
  2.Loaders将Aspired versions送到manager,manafer load它们,被将它们用来服务来自客户端的请求。
更多的细节:
  1.一个Source为具体的版本创建一个Loader.这个loader包含去load一个servable所需要的一切资源。
  2.Source通过回传通知Manager Aspired version是什么
  3.Manager通过配置的版本文件决定下一步的动作,可能是unload先前的版本或者load一个新的版本
  4.如果Manager确定它是安全的,他就给Loader需要的资源并且告诉Loader去load一个新的版本
  5.客户端向Manager要Servable,或者具体的某个版本或者仅仅只是请求最新的版本,Manager返回Servable的句柄。

举例来说:
一个Source(代表一个Tf 图,它的权重时常更新,这些权重被存储在文件或者磁盘里)
  1.Source检测到模型权重更新到一个新的版本,它创建一个Loader,其包含一个指向模型数据的指针。
  2.Source通知Manager Aspired version
       3. Manager通过版本策略决定去load一个新的版本
  4.Manager告诉loader内存足够,Loader用新的权重实例化TF图
  5.客户端请求模型的最新版本,Manager返回一个Servable的句柄


5.Extensibility(可扩展性)
TensorFlow服务提供了几个扩展点,您可以在其中添加新功能

6.Version Policy(上文提到的版本策略)
版本策略指定单个可流式流中版本加载和卸载
TensorFlow服务包括两个适用于大多数已知用例的策略。 这些是可用性保护策略(避免加载零版本;通常在卸载旧版本之前加载新版本)和资源保存策略(避免同时加载两个版本,从而需要两倍资源;卸载旧版本之前加载 一个新的)。 为了简单地使用TensorFlow服务,其中模型的可用性很重要且资源成本低,则可用性保留策略将确保在卸载旧版本之前加载并准备好新版本。 对于TensorFlow服务的复杂使用,例如跨多个服务器实例管理版本,资源保护策略需要最少的资源(无需额外的缓冲区来加载新版本)。














2017年8月3日星期四

shell ,bash,tmux

笔者对这几个命令一直很不了解,搜到一篇好文章,准备有时间看,记录如下:
Shell的相关概念和配置方法

优雅地使用命令行:Tmux 终端复用 

Linux下终端利器tmux

隔壁大神的博客: tmux安装使用

记录一下:
linux下常用命令,有时间再看
awk sed wc grep
cat more less
netstat

2017年7月30日星期日

关于端口占用的一些问题

笔者在使用tensorboard时,由于运行代码失误,不小心多次占用了6006端口。
笔者企图用ps来查看进程:







但是其并没有显示出占用6006号端口的进程。
隔壁大神帮忙,
输入命令 netstat -lntp 查看了进程占用的端口号,找到了相应进程

然后使用命令 ps -ef | grep 5037
[1]ps:将某个进程显示出来
-A  显示所有程序。
-e  此参数的效果和指定"A"参数相同。
-f  显示UID,PPIP,C与STIME栏位。
grep命令是查找
中间的|是管道命令 是指ps命令与grep同时执行

最后使用kill -9 5037 来kill进程号为5037的进程


参考:[1]http://blog.csdn.net/lgstudyvc/article/details/51916268

2017年7月26日星期三

seq2seq:beamSearch算法学习

笔者大病初愈,又开始继续学习。在对话系统的解码阶段,会用到beamSearch算法。笔者今天粗略的看了下,理解为如下意思。仅供参考。

 如果笔者后续有更深入的理解,会来补充的

2017年7月20日星期四

一些工作上的小细节


1.开多个终端界面,用ctrl+shift+t;若干终端之间切换,用alt+(1...n)

word2vec

笔者最近做的项目里涉及到LSTM,也涉及了wordembedding.找一篇博客先进行理解,后面在加一个自己的理解。
现推荐一篇超级棒的博客:
http://blog.csdn.net/itplus/article/details/37969519

leetcode 17

17.   Letter Combinations of a Phone Number Medium Given a string containing digits from   2-9   inclusive, return all possible l...