-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsearch.xml
More file actions
93 lines (93 loc) · 30.2 KB
/
search.xml
File metadata and controls
93 lines (93 loc) · 30.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[Hello World]]></title>
<url>%2Fpost%2F4a17b156.html</url>
<content type="text"><![CDATA[Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub. Quick StartCreate a new post1$ hexo new "My New Post" More info: Writing Run server1$ hexo server More info: Server Generate static files1$ hexo generate More info: Generating Deploy to remote sites1$ hexo deploy More info: Deployment]]></content>
</entry>
<entry>
<title><![CDATA[fasttext source code reading]]></title>
<url>%2Fpost%2F28086dee.html</url>
<content type="text"><![CDATA[fasttext整个实现并不复杂,整个工程简洁,清楚,是个很好的开源项目,适合我这种新手作为源码阅读的起步。 project architecture拿到一份代码之后,首先得分析整个工程的结构,能让你看清楚一个project的结构的有两部分,一部分是main函数,还有一部分是头文件.h。 123456789101112131415161718192021222324252627282930313233int main(int argc, char** argv) { std::vector<std::string> args(argv, argv + argc); if (args.size() < 2) { printUsage(); exit(EXIT_FAILURE); } std::string command(args[1]); if (command == "skipgram" || command == "cbow" || command == "supervised") { train(args); } else if (command == "test") { test(args); } else if (command == "quantize") { quantize(args); } else if (command == "print-word-vectors") { printWordVectors(args); } else if (command == "print-sentence-vectors") { printSentenceVectors(args); } else if (command == "print-ngrams") { printNgrams(args); } else if (command == "nn") { nn(args); } else if (command == "analogies") { analogies(args); } else if (command == "predict" || command == "predict-prob") { predict(args); } else if (command == "dump") { dump(args); } else { printUsage(); exit(EXIT_FAILURE); } return 0;} 从main函数中可以看到整个fasttext有哪些功能。现在我从train(args)入手,看fasttext训练embedding的整个过程。 train1234567891011void train(const std::vector<std::string> args) { Args a = Args(); // 参数解析的类 a.parseArgs(args); //解析参数 FastText fasttext; // fasttext类 fasttext.train(a); // 训练 fasttext.saveModel(); // 保存模型 fasttext.saveVectors(); // 保存训练好的embedding if (a.saveOutput) { fasttext.saveOutput(); }} 那么,接下来重点就放到一个Args参数解析类和fasttext类上。 Args可以看到,Args类的成员变量就是fasttext需要的参数。参数的具体意义可以在这里找到link 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647class Args { protected: std::string lossToString(loss_name) const; std::string boolToString(bool) const; std::string modelToString(model_name) const; public: Args();// 构造函数 std::string input; std::string output; double lr; // learning rate int lrUpdateRate; // change the rate of updates for the learning rate int dim; // embedding 维度 int ws; // size of context window int epoch; // 迭代次数 int minCount; int minCountLabel; int neg; // number of negatives sampled int wordNgrams; loss_name loss; model_name model; int bucket; int minn; int maxn; int thread; double t; std::string label; int verbose; std::string pretrainedVectors; bool saveOutput; bool qout; bool retrain; bool qnorm; size_t cutoff; size_t dsub; void parseArgs(const std::vector<std::string>& args); void printHelp(); void printBasicHelp(); void printDictionaryHelp(); void printTrainingHelp(); void printQuantizationHelp(); void save(std::ostream&); void load(std::istream&); void dump(std::ostream&) const;}; 构造函数里面给成员变量赋初值,从这个类里面学会了enum class的妙用,enum class 是c++ 11的特性,link1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980enum class loss_name: int {hs=1, ns, softmax};std::string Args::lossToString(loss_name ln) const { switch (ln) { case loss_name::hs: return "hs"; case loss_name::ns: return "ns"; case loss_name::softmax: return "softmax"; } return "Unknown loss!"; // should never happen}class Model { protected: std::shared_ptr<Matrix> wi_; std::shared_ptr<Matrix> wo_; std::shared_ptr<QMatrix> qwi_; std::shared_ptr<QMatrix> qwo_; std::shared_ptr<Args> args_; Vector hidden_; Vector output_; Vector grad_; int32_t hsz_; int32_t osz_; real loss_; int64_t nexamples_; std::vector<real> t_sigmoid_; std::vector<real> t_log_; // used for negative sampling: std::vector<int32_t> negatives_; size_t negpos; // used for hierarchical softmax: std::vector< std::vector<int32_t> > paths; std::vector< std::vector<bool> > codes; std::vector<Node> tree; static bool comparePairs(const std::pair<real, int32_t>&, const std::pair<real, int32_t>&); int32_t getNegative(int32_t target); void initSigmoid(); void initLog(); static const int32_t NEGATIVE_TABLE_SIZE = 10000000; public: Model(std::shared_ptr<Matrix>, std::shared_ptr<Matrix>, std::shared_ptr<Args>, int32_t); real binaryLogistic(int32_t, bool, real); real negativeSampling(int32_t, real); real hierarchicalSoftmax(int32_t, real); real softmax(int32_t, real); void predict(const std::vector<int32_t>&, int32_t, real, std::vector<std::pair<real, int32_t>>&, Vector&, Vector&) const; void predict(const std::vector<int32_t>&, int32_t, real, std::vector<std::pair<real, int32_t>>&); void dfs(int32_t, real, int32_t, real, std::vector<std::pair<real, int32_t>>&, Vector&) const; void findKBest(int32_t, real, std::vector<std::pair<real, int32_t>>&, Vector&, Vector&) const; void update(const std::vector<int32_t>&, int32_t, real); void computeHidden(const std::vector<int32_t>&, Vector&) const; void computeOutputSoftmax(Vector&, Vector&) const; void computeOutputSoftmax(); void setTargetCounts(const std::vector<int64_t>&); void initTableNegatives(const std::vector<int64_t>&); void buildTree(const std::vector<int64_t>&); real getLoss() const; real sigmoid(real) const; real log(real) const; real std_log(real) const; std::minstd_rand rng; bool quant_; void setQuantizePointer(std::shared_ptr<QMatrix>, std::shared_ptr<QMatrix>, bool);}; 我更关心的是fasttext类,所以赶紧去看看fasttext.h。 fasttext这里就不放代码了,还是从fasttext.h入手,我关心这几个方面,一个方面是输入是如何读取的,第二个是如何训练的,用的什么数据结构,第三个是模型存储是怎么做到的,用的什么方式。在这个头文件中,看到std::shared_ptr,这是c++11的特性,传统的动态内存分配和释放使用new和delete,但是很容易出现忘记释放内存的情况,这个时候智能指针就解决了这个问题,它自动释放内存,是模板,初始化的方法和vector是一样的,存在头文件memory中。另外一个就是使用了很多const,TODO 。找到fasttext.cc,找到train函数,其中输入数据读取是由下面这个函数解决的。 123456789dict_ = std::make_shared<Dictionary>(args_);std::ifstream ifs(args_->input);if (!ifs.is_open()) { throw std::invalid_argument( args_->input + " cannot be opened for training!" );} dict_->readFromFile(ifs); ifs.close();` 接下去就该去dictionary.h中寻找输入读取的细节。首先找到readFromFile这个函数,比较关键的几个函数分别是readWord(word),add(word),threshhold, initTableDiscard和initNgrams。 先去看readWord,发现这个函数就是读取一个词的,分割符号类似" ", "\r", "\t"之类的 add的实现有些技巧,使用了hash的方式将词进行编码,这样在查找词的时候就会更快,hash采用的32位的NFV算法,词被存在words_里面,它是个vector,每个元素是一个entry的结构体,包含了这个词,词的词频,以及是label还是word,还有子单词的信息。 threshold是为了去掉频率过低和过高的词,这里用到了lambda表达式1234words_.erase(remove_if(words_.begin(), words_.end(), [&](const entry& e) { return (e.type == entry_type::word && e.count < t) || (e.type == entry_type::label && e.count < tl); }), words_.end()); remove_if和erase一般成对出现,lambda表达式查阅link同时,vector里面使用了函数shrink_to_fit,这个函数可以释放掉vector中被erase掉的内存空间。 initTableDiscard,从新计算一个词的词频,并把计算的词频放到pdiscard_中,这里采用了一个技巧,计算词频的时候做了一个缩放\sqrt{x/f}+x/f,其中f取0.0001,这样能保证f过小的时候整个数不会太大,f过大的时候整个值也不会太小。 1234567void Dictionary::initTableDiscard() { pdiscard_.resize(size_); for (size_t i = 0; i < size_; i++) { real f = real(words_[i].count) / real(ntokens_); pdiscard_[i] = std::sqrt(args_->t / f) + args_->t / f; }} initNgrams主要部分在computeSubwords这个函数中,所以找到这个函数分析。 1if ((word[i] & 0xC0) == 0x80) continue; 这句话为了检测编码是不是10开头的utf-8,因为10开始的utf-8编码,表示一个多字节序的子序,具体的可以参见reference.数据处理这部分就算差不多了,接着去看模型训练的过程. 还是接着看train函数,loadVector这个函数就没什么好看的了,就是从文件中读取训练好的embedding.接下来,看到这段代码的时候,这就是开始了模型的训练,两个模块比较重要,一个是startThreads(),另外一个就是Model。123456789startThreads();model_ = std::make_shared<Model>(input_, output_, args_, 0);if (args_->model == model_name::sup) { model_->setTargetCounts(dict_->getCounts(entry_type::label)); } else { model_->setTargetCounts(dict_->getCounts(entry_type::word));} startThreads 把线程放到vector中,用lambda表达式的值传递方式建立线程,之后采用join方式阻塞线程。 1234567std::vector<std::thread> threads;for (int32_t i = 0; i < args_->thread; i++) { threads.push_back(std::thread([=]() { trainThread(i); }));}for (int32_t i = 0; i < args_->thread; i++) { threads[i].join();} Model 先将Model分析清楚再去分析trainThread函数,找到Model.h,这个类就是整个fasttext的核心算法所在了。Model里面包含了很多东西,有关quantize的先放到后面分析,看README知道这是后面增加的feature,这个方式下内存占用会变小,这其实就是对网络做了一个压缩。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869class Model { protected: std::shared_ptr<Matrix> wi_; //连接input的权值,其中Matrix类以vector存储了二维的数组,并定义了很多类方法,比如l2NormRow, dotRow等等 std::shared_ptr<Matrix> wo_; //连接output的权值 std::shared_ptr<QMatrix> qwi_; std::shared_ptr<QMatrix> qwo_; std::shared_ptr<Args> args_; Vector hidden_; // 隐藏层单元,Vector类以vector存储隐层单元的值,也定义了很多基于vector的方法 Vector output_; // 输出层,类型也是Vector Vector grad_; // 梯度值 int32_t hsz_; int32_t osz_; real loss_; // loss值,real即为float int64_t nexamples_; // 样本总数 std::vector<real> t_sigmoid_; // 经过sigmoid之后的值 std::vector<real> t_log_; //经过 // used for negative sampling: std::vector<int32_t> negatives_; size_t negpos; // used for hierarchical softmax: std::vector< std::vector<int32_t> > paths; std::vector< std::vector<bool> > codes; //存储哈夫曼编码 std::vector<Node> tree; //存储这个编码树 static bool comparePairs(const std::pair<real, int32_t>&, const std::pair<real, int32_t>&); int32_t getNegative(int32_t target); void initSigmoid(); void initLog(); static const int32_t NEGATIVE_TABLE_SIZE = 10000000; public: Model(std::shared_ptr<Matrix>, std::shared_ptr<Matrix>, std::shared_ptr<Args>, int32_t); real binaryLogistic(int32_t, bool, real); // logistic回归 real negativeSampling(int32_t, real); // negative sampling 方法 real hierarchicalSoftmax(int32_t, real); // hs方法 real softmax(int32_t, real); // softmax方法 void predict(const std::vector<int32_t>&, int32_t, real, std::vector<std::pair<real, int32_t>>&, Vector&, Vector&) const; // predict方法 void predict(const std::vector<int32_t>&, int32_t, real, std::vector<std::pair<real, int32_t>>&); void dfs(int32_t, real, int32_t, real, std::vector<std::pair<real, int32_t>>&, Vector&) const; // 深度优先遍历方法 void findKBest(int32_t, real, std::vector<std::pair<real, int32_t>>&, Vector&, Vector&) const; // 选出k个最近的 void update(const std::vector<int32_t>&, int32_t, real); //计算梯度,更新权值 void computeHidden(const std::vector<int32_t>&, Vector&) const; //计算hidden的值 void computeOutputSoftmax(Vector&, Vector&) const;//计算经过softmax后的值 void computeOutputSoftmax(); void setTargetCounts(const std::vector<int64_t>&); void initTableNegatives(const std::vector<int64_t>&); void buildTree(const std::vector<int64_t>&);// 建立哈夫曼树 real getLoss() const; real sigmoid(real) const; real log(real) const; real std_log(real) const; std::minstd_rand rng; bool quant_; void setQuantizePointer(std::shared_ptr<QMatrix>, std::shared_ptr<QMatrix>, bool);}; trainThread 分析完Model的结构,转回trainThread,这个threadId主要是为了给各个线程分配不同的数据。然后有三个模型,分别是supervised,skipgram和cbow,这里选择一个模型supervised继续下面的分析。 12345678910void FastText::supervised( Model& model, real lr, const std::vector<int32_t>& line, const std::vector<int32_t>& labels) { if (labels.size() == 0 || line.size() == 0) return; std::uniform_int_distribution<> uniform(0, labels.size() - 1); // 均匀分布 int32_t i = uniform(model.rng); model.update(line, labels[i], lr);} Reference https://github.com/facebookresearch/fastText/tree/master/src https://stackoverflow.com/questions/3911536/utf-8-unicode-whats-with-0xc0-and-0x80 http://blog.sina.com.cn/s/blog\_7c4f3b160101dv4p.html]]></content>
<categories>
<category>blog</category>
</categories>
<tags>
<tag>c++</tag>
<tag>fasttext</tag>
<tag>tool</tag>
</tags>
</entry>
<entry>
<title><![CDATA[DianNao Accelerator]]></title>
<url>%2Fpost%2F400a901a.html</url>
<content type="text"><![CDATA[文章主要关注点在feed forward,而不是back propagation。从deep network中选取了两种比较有代表性的网络结构CNN 和DNN,接着又从这两个网络里面提取了三个具有代表性的layer,分别是 classsifier, convolutional layer 和 pooling layer。如下图, 要加速神经网络,memory traffic显然是一个很重要的方面,接下类分析这三个layer的data locality,通过tiling调整三个layer作为baseline.用了cache simulator来测出memory bandwidth, 其中cachesimulator所需要的输入应该是用模拟器产生的,模拟器可以由 Gem5 改写而成。文中做了一个假设,那就是循环的每一轮都能处理T_n个neurons和T_i个synapses。 classifier layer 一个classifier layer写出表达式如下,如果略掉偏执b,那么其实就是一个向量乘以一个矩阵,我们看这个向量其实会用很多次,如果向量一直存在cache中,那么访存就会少很多。学体系结构的人都知道,程序的大部分时间都花在了访存上了,所以通过减少访存的次数,可以减少运行时间。loop tiling是很常用的方法,思想就是将数据局部性好的数据尽量都保持在cache中。数据局部性包含两部分,一部分是temporal locality,这是时间上的,就是说经常用到。一部分是spacial locality,就是空间上了,存储在连续空间的数据spacial locality会比较好。 y=xw+b pooling layer convolutional layer]]></content>
<categories>
<category>blog</category>
</categories>
<tags>
<tag>DL</tag>
<tag>convolution</tag>
<tag>accelerator</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Attention based text translation and document classification]]></title>
<url>%2Fpost%2Fb2144cbd.html</url>
<content type="text"><![CDATA[下图是attention机制在机器翻译上的表现,可以看到attention很好的解决了长句子级的机器翻译问题。 下面我们从文本翻译来讲解attention机制,传统的文本翻译一般是encoder-decoder的结构,如下图。现在将英文句子X翻译成中文句子Y,两个句子各自由不同的单词序列组成,表示如下, X= \\ Y= 其中,encoder负责对输入的句子进行编码,将句子通过非线性变换转化为中间语义表示$C$,表示为$C=E(x_1,x_2…x_m)$。decoder根据X的中间语义$C$和之间的历史信息$y_1, y_2…y_{i-1}$来生成i时刻的单词$y_i$,表示为$y_i = D(y_1,y_2…y_{i-1})$。 那么attention机制是怎么一回事呢。先举个例子,假设X序列为Jack love Rose,Y序列为杰克喜欢罗斯。我们用分解encoder-decoder的过程,那么翻译的过程就是依次生成杰克、喜欢、罗斯,表示为 y_1 = D(C) \\ y_2 = D(C,y_1) \\ y_3 = D(C,y_1,y_2)传统的语义表示方法的局限就体现出来了,在生成目标句子的单词的时候,无论是 $y_1$ , $y_2$ 还是 $y_3$ ,都使用的语义编码C,没有变化,换句话来说就是句子X中的任意单词对于生成目标单词$y_i$的影响都是一样的,这明显是不科学的。attention就是为了解决这个不合理的地方,比如在翻译出喜欢这个词的时候,love的贡献率应该更大,而Jack和Rose就显得不那么重要了。注意力机制要体现英文单词对于翻译当前中文单词的不同影响程度,类似于给出一个概率分布值,比如在翻译出喜欢这个词的时候,表示为$(Jack,0.3)(love,0.5)(Rose,0.2)$。 引入注意力机制之后,目标句子中的每个单词都会学习对应源句子中每个单词的注意力分配概率的信息。这就相当于在生成每个单词$y_i$的时候,都会根据$y_1,y_2…y_{i-1}$来生成新的变化的$c_i$,模型结构如下图,翻译的过程就变成了下面这个过程 y_1 = D(C_1) \\ y_2 = D(C_2,y_1) \\ y_3 = D(C_3,y_1,y_2) 对于上面那个例子,其对应的翻译过程可能如下,其中$F$函数是encoder对英文单词的变换函数,如果是RNN模型,那么$F$对应的结果是某个时刻隐层节点的状态值,$G$函数代表encoder根据单词的中间表示合成整个句子中间语义表示的变换函数,一般是对构成元素加权求和。 c_{杰克} =G(0.6*F('Jack'),0.2*F('love),0.2*F('Rose')) \\ c_{喜欢} =G(0.2*F('Jack'),0.7*F('love),0.1*F('Rose')) \\ c_{罗斯} =G(0.2*F('Jack'),0.3*F('love),0.5*F('Rose'))以RNN作为encoder和decoder,那么传统的文本翻译的过程就如下图,经过一个RNN的encoder将一句话的语义全部放在了一个矩阵C中,然后再通过decoder翻译出来,这样看来就更能看出整个模型的缺点了,这在长句子翻译上的表现差就很容易解释了,因为长句子蕴含的信息量更大,但仍旧只是把句子的语义映射到一个固定大小的矩阵中去,这没办法完整地表示整个句子的语义。 attention的结构,就是将之前的隐层单元输出都收集起来,对这些输出做了个加权求和,这个权值体现了源句子中每个词对于当前需要翻译的词的贡献,结构如下图, 总结下,attention机制,就像人在足球比赛,每个时刻,注意力都可能放到不同的人身上,C罗带球了,你可能关注点放到了C罗身上,梅西射门了,那么你肯定更关注这个球进没进,梅西脚下动作是什么,相比之下,其他后卫的跑位,掩护可能都没有这些东西更吸引你关注。这个关注就是attention机制,相当于你大脑给这个事件更大的权重。又比如,你读一本小说,需要读懂当前情节,就需要之前的铺垫和背景知识,但是不是所有的背景知识对于理解当前情节都是很重要的,这个重要程度就是attention机制。简而言之,attention机制解决了之前的模型抓不住重点的问题. Attention for document classificationhierarchical attention network描述了文档的结构,文档是由句子构成的,句子是由单词构成的。又加入了两个层次的attention机制,一个是句子级的,一个是单词级的,给出了单词和句子对于整个信息的不同贡献程度。一个文档有$L$个句子$s_i$,每个句子有$T_i$个词,$w_{it}$表示第i句话中的第t个词 word encoder 一开始,需要通过embedding矩阵$We$转化为对应的embedding,然后通过双向的GRU,获得前向的hidden state,和反向的hidden state,组合成为一个新的$h\{it}$,这样都把这个词的语义用周围的词表示出来了。 word attention 不是所有的词都是一句话的重点,所以,引入了attention的机制。先让$h_it$通过一个单层的MLP,得到$h_{it}$的隐层表示$u_{it}$,然后通过计算$u_{it}$和$u_w$之间的相似度来衡量这个词对于句子语义的重要程度。$u_w$随机初始化的,通过训练学习得到。通过softmax,最后对所有单词加权和得到句子的表示$s_i$。 sentence encoder 不是所有的句子都是一个文档的重点,所以,在句子级也引入了attention机制。同理,对于每个句子$s_i$,前向和后向的hidden units组合成一个新的$h_{it}$,然后通过同样的方式引入attention,最后加权求和得到整个文档的语义表示$v$。 sentence attention Reference http://www.cs.cmu.edu/~./hovy/papers/16HLT-hierarchical-attention-networks.pdf https://github.com/richliao/textClassifier https://github.com/ematvey/hierarchical-attention-networks http://blog.csdn.net/malefactor/article/details/50550211]]></content>
<categories>
<category>deep learning</category>
<category>NLP</category>
</categories>
<tags>
<tag>DL</tag>
<tag>attention</tag>
<tag>document classification</tag>
</tags>
</entry>
<entry>
<title><![CDATA[gitlab workflow]]></title>
<url>%2Fpost%2Fbd2c5685.html</url>
<content type="text"><![CDATA[gitlab作为一个协同工作的代码管理工具,使用起来很方便,能大大提高生产效率。 git的工作流主要维护本地仓库的三棵树,分别是工作目录,包含了实际的文件;暂存区(Index),相当于一个缓冲区,保存临时改动;HEAD,指向最后一次提交的结果。 1. easy workflowtake demo.cpp for example git add demo.cpp demo.cpp被添加到暂存区 git commit -m "demo cpp" 提交改动到HEAD,但还没有提交到远程分支 git pull origin branch-name 从远程分支上pull到本地,更新本地分支 git push origin branch-name 提交改动到远程分支branch-name上 2. branch一般在创建一个repository之后,会有一个默认的分支master。现在,在本地建立一个新的分支feature_x,使用命令git checkout -b feature_x,就在本地新建了一个分支,并同时切换到该分支上,这个分支相当于另外一个工作区。使用命令git checkout master就切换回master了。git push origin feature_x本地新建的分支就被推送到远程,远程多了一个分支feature_x。要删除分支,使用命令git branch -d feature_x 3. merge在工业生产中,每个人会在一个对应的分支上开发自己的feature,完成开发之后提交MR,然后通过review,和CI,最终merge到master上。这样保证了项目的质量,同时提高工作效率。git merge feature_x,提交了feature_x和master的MR。 当你在merge或者是pull的时候可能会出现conflicts,那么你需要先修改好这些冲突,然后使用git add添加修改好的文件,再进行后续的步骤。 4. git rebasegit rebase主要作用是将一个分支的修改合并到当前的分支,下面以一个例子来讲解 现在有一个远程分支origin,已经有了两个commits,然后基于origin分支新建一个mywork分支 你在mywork分支上有了两个commits,你的同事在origin上也提交了两个commits,两个分支各自都前进了,那么就产生了分叉 你在提交MR之前会先会使用git pull更新本地分支,那么两个分支就会产生merge,看起来就是这样的 如果你想要mywork分支像没有经过合并一样,需要使用git rebase,这样会把mywork分支中的commits临时保存在.git/rebase中,然后更新mywork为最新的origin分支,接着再把这些临时保存的修改应用到mywork上,这样,看起来就跟没有合并一样,结构更为清爽,便于repository的管理。 当mywork分支更新之后,之前的commits就会被丢掉,垃圾回收机制就会把这些没有用的commits给删除掉 如果git rebase的过程中出现了conflicts,那么可以先解决玩冲突,然后使用git add添加修改,接着使用git rebase --continue 5. conflicts多人协作的时候,很容易产生conflicts,这时候需要我们先在本地解决好冲突,然后再进行后面的步骤。冲突表现为下图这样,在<<<<<<和HEAD之间是你当前的修改,后面那部分是别人的修改或者是你之前的修改。如果两个工作都需要,那么把所有的非代码部分去掉就可以了,如果只需要其中一个,那就保留其中一个。 6. other commands git stash 用作你有一些修改,但是又不想提交这些修改,同时你又要回到一个干净的工作环境。这个命令就会把你在工作环境中和Index下的修改放到一个缓冲区去,然后把工作环境revert到最近的一个commits(HEAD)。 git stash pop 弹出之前保存的修改 git log 查看git的日志,所有提交的commits。可以按照树形显示分支,git log --graph --oneline --decorate --all Reference http://rogerdudler.github.io/git-guide/index.zh.html https://team-coder.com/avoid-merge-conflicts/ http://blog.csdn.net/hudashi/article/details/7664631/ https://git-scm.com/docs/git-rebase https://team-coder.com/from-git-flow-to-trunk-based-development/]]></content>
<categories>
<category>blog</category>
</categories>
<tags>
<tag>gitlab</tag>
<tag>tools</tag>
</tags>
</entry>
<entry>
<title><![CDATA[imbalanced machine learning]]></title>
<url>%2Fpost%2F8ba6d402.html</url>
<content type="text"><![CDATA[先占个位置,后续添加]]></content>
<categories>
<category>blog</category>
</categories>
<tags>
<tag>imbalance data</tag>
</tags>
</entry>
<entry>
<title><![CDATA[recommender system]]></title>
<url>%2Fpost%2F7dc7a8c3.html</url>
<content type="text"><![CDATA[先占个位置,后续添加, 仅仅测试一下子, 看看这个语法还能行不 搞得我头大了 嘛单的 这是神码]]></content>
<tags>
<tag>recommender</tag>
</tags>
</entry>
<entry>
<title><![CDATA[recurrent neural networks]]></title>
<url>%2Fpost%2F5e52465.html</url>
<content type="text"><![CDATA[Introduce basics knowledges about recurrent neural networks ! RNN下图是一个RNN循环展开的示意图,$x_t$是t时刻的输入,$s_t$是隐藏单元,$s_t=f(Ux_t+Ws_{t-1})$,激活函数f常用tanh和RELU.RNN的参数是共享的,即图中的U,V,W都是共享的参数.隐藏单元s是RNN的feature所在,包含了一个序列的特征。RNN的训练采用BPTT算法进行反向传播。 BPTT 【1】 forward $s_t=f(Ux_t+Ws_{t-1})$以及$o_t = softmax(Vs_t)$ 【2】 cross entropy $E(y,\hat{y})=-\sum_t{y_tlog{\hat{y_t}}}$ 【3】 backward 目标是计算误差对于参数U,V和W的梯度。将每个时刻的梯度相加$\frac{dE}{dW}=\sum_t{\frac{dE_t}{dW}}$ , $\frac{dE}{dV}=\sum_t{\frac{dE_t}{dV}}$ ,$\frac{dE}{dU}=\sum_t{\frac{dE_t}{dU}}$. V的梯度每个时刻是独立的,不依赖于别的时刻, t时刻,$\frac{dE_t}{dV}=(\hat{y_t}-y_t)\otimes{s_t}$. 计算W的梯度却不太一样,根据链式求导法则, \frac{dE_t}{dW}=\frac{dE_t}{d{\hat{y_t}}}\frac{d{\hat{y_t}}}{ds_t}\frac{ds_t}{dW}又由于$s_t=f(Ux_t+Ws_{t-1})$,t时刻的输出依赖于t-1时刻,所以$s_{t-1}$也要使用链式求导法则,那么得到 \frac{dE_t}{dW}=\sum_{k=0}^t\frac{dE_t}{d{\hat{y_t}}}\frac{d{\hat{y_t}}}{ds_t}\frac{ds_t}{ds_k}\frac{ds_k}{dW}以下图为例,计算$s_3$的链式求导,$\frac{ds_3}{dz_2}=\frac{ds_3}{ds_2}\frac{ds_2}{ds_1}\frac{ds_1}{ds_0}$,其中$z_2=Ux_1+Ws_1$ LSTM一个标准的lstm内部结构如下图,包含四个单元 forget gate 激活函数为sigmoid,输出为1,完全通过,输出为0,完全丢失。 存储单元 通过$i_t$来选择是否让$\tilde{C_t}$加入到输出中 接下来是$\tilde{C_t}$的输出 以下面的几个公式来总结一下lstm, \hat{h_t} = W_{hx}x_t+W_{hh}h_{t-1}\\ i_t = \sigma(W_{ix}x_t+W_{ih}h_{t-1})\\ o_t = \sigma(W_{ox}x_t+W_{oh}h_{t-1})\\ f_t = \sigma(W_{fx}x_t+W_{fh}h_{t-1})\\ c_t = f_t\odot{c_{t-1}}+i_t\odot{\hat{h_t}} \\ h_t = tanh(c_t\odot{o_t})mLSTM m_t = (W_{mx}x_t)\odot(W_{mh}h_{t-1}) \\ \hat{h_t} = W_{hx}x_t+W_{hh}m_t \\ i_t = \sigma(W_{ix}x_t+W_{ih}m_t) \\ o_t = \sigma(W_{ox}x_t+W_{oh}m_t) \\ f_t = \sigma(W_{fx}x_t+W_{fh}m_t) \\References http://colah.github.io/posts/2015-08-Understanding-LSTMs/ http://www.cs.toronto.edu/%7Eilya/pubs/2011/LANG-RNN.pdf?ref=driverlayer.com https://arxiv.org/abs/1609.07959]]></content>
<categories>
<category>deep learning</category>
<category>rnn</category>
</categories>
<tags>
<tag>rnn</tag>
<tag>lstm</tag>
<tag>DL</tag>
</tags>
</entry>
</search>