HttpServerModule的请求主要由HttpServer中的HttpServerTransport (默认为NettyHttpServerTransport)类处理。
NettyHttpServerTransport基于netty框架,负责监听并建立连接,信息的处理由内部类HttpChannelPipelineFactory 完成。
每当产生一个连接时,都会发出一个ChannelEvent,该Event由一系列的ChannelHandler进行处理。
为了方便组织,这些ChannelHandler被放在一条“流(pipeline)”里,一个ChannelEvent并不会主动的”流”经所有的Handler,而是由上一个Handler显式的调用ChannelPipeline.sendUp(Down)stream产生,并交给下一个Handler处理。
换句话说,每个Handler接收到一个ChannelEvent,并处理结束后,如果需要继续处理,那么它需要调用sendUp(Down)stream新发起一个事件。如果它不再发起事件,那么处理就到此结束,即使它后面仍然有Handler没有执行。这个机制可以保证最大的灵活性,当然对Handler的先后顺序也有了更严格的要求。
在流Pipeline里有一个Map(name2ctx)和一个链表(记录head和tail),pipeline里面会调度关联的多个channelhandler的运行。
在NettyHttpServerTransport中,会流过的channelhandler就包括解码http请求(把多个HttpChunk拼起来并按http协议进行解析)和http请求处理。
在处理http请求,数据流向为:HttpRequestHandler->NettyHttpServerTransport->HttpServerAdapter(HttpServer的内部类Dispatche)->RestController。
RestController中的处理代码为:
void executeHandler(RestRequest request, RestChannel channel) throws Exception {
        final RestHandler handler = getHandler(request);
        if (handler != null) {
            handler.handleRequest(request, channel);
        } else {
            if (request.method() == RestRequest.Method.OPTIONS) {
                // when we have OPTIONS request, simply send OK by default 
                // (with the Access Control Origin header which gets automatically added)
                channel.sendResponse(new BytesRestResponse(OK));
            } else {
                channel.sendResponse(new BytesRestResponse(
                    BAD_REQUEST, 
                    "No handler found for uri [" + request.uri() + "] and method [" + request.method() + "]"
                ));
            }
        }
    }
    private RestHandler getHandler(RestRequest request) {
        String path = getPath(request);
        RestRequest.Method method = request.method();
        if (method == RestRequest.Method.GET) {
            return getHandlers.retrieve(path, request.params());
        } else if (method == RestRequest.Method.POST) {
            return postHandlers.retrieve(path, request.params());
        } else if (method == RestRequest.Method.PUT) {
            return putHandlers.retrieve(path, request.params());
        } else if (method == RestRequest.Method.DELETE) {
            return deleteHandlers.retrieve(path, request.params());
        } else if (method == RestRequest.Method.HEAD) {
            return headHandlers.retrieve(path, request.params());
        } else if (method == RestRequest.Method.OPTIONS) {
            return optionsHandlers.retrieve(path, request.params());
        } else {
            return null;
        }
    }
void executeHandler(RestRequest request, RestChannel channel) throws Exception { final RestHandler handler = getHandler(request); if (handler != null) { handler.handleRequest(request, channel); } else { if (request.method() == RestRequest.Method.OPTIONS) { // when we have OPTIONS request, simply send OK by default (with the Access Control Origin header which gets automatically added) channel.sendResponse(new BytesRestResponse(OK)); } else { channel.sendResponse(new BytesRestResponse(BAD_REQUEST, “No handler found for uri [” + request.uri() + “] and method [” + request.method() + “]”)); } } }
Tornado是一款轻量级的Web服务器,同时又是一个开发框架。采用单线程非阻塞I/O模型(epoll),主要是为了应对高并发 访问量而被开发出来,尤其适用于comet应用。
Tornado服务器3大核心模块:
(1) IOLoop
Tornado为了实现高并发和高性能,使用了一个IOLoop来处理socket的读写事件,IOLoop基于epoll,可以高效的响应网络事件。这是Tornado高效的保证。
tornado.ioloop.IOLoop.instance().start()
IOLoop使用了单例模式,处理所有IO事件,
实现为EPollIOLoop->PollIOLoop->IOLoop->Configurable
IOLoop中有四个重要的数据集: _events 和 _handlers 保存I/O事件和对应的处理器, _callbacks 和 _timeouts 保存(超时)回调。
关键函数:
def initialize(self, impl, time_func=None):
    super(PollIOLoop, self).initialize()
    self._impl = impl
    if hasattr(self._impl, 'fileno'):
        set_close_exec(self._impl.fileno())
    self.time_func = time_func or time.time
    #handlers 是一个函数集字典
    self._handlers = {}
    self._events = {}
    #回调函数集合
    self._callbacks = []
    self._callback_lock = threading.Lock()
    self._timeouts = []
    self._cancellations = 0
    self._running = False
    self._stopped = False
    self._closing = False
    self._thread_ident = None
    self._blocking_signal_threshold = None
    self._timeout_counter = itertools.count()
    # Create a pipe that we send bogus data to when we want to wake
    # the I/O loop when it is idle
    self._waker = Waker()
    self.add_handler(self._waker.fileno(),
                     lambda fd, events: self._waker.consume(),
                     self.READ)
其中,waker是一个发伪数据用的类,在需要时,我们可以用它唤醒空闲的I/O Loop。当我们调用add_callback时,为了让回调函数运行,可能会需要使用它发送一个伪数据。
最近在做搜索,抽空看一下lucene,资料挺多的,不过大部分都是3.x了……在对着官方文档大概看一下。
优化后的lucene索引文件(4.9.0)

一、段文件
1.段文件:segments_5p和segments.gen。
segments.gen保存当前段文件版本信息。
- segments.gen: GenHeader, Generation, Generation, Footer
 
segments_N(segments_5p)保存最新的段的信息,包括段的个数,每个段的段名、文档数等信息。
- 
    segments_N: Header, Version, NameCounter, SegCount, 
SegCount, CommitUserData, Footer  
源码参考:SegmentInfos.read(Directory directory, String segmentFileName):
2.段信息:*.si,存储段的基本信息。
- .si: Header, SegVersion, SegSize, IsCompoundFile, Diagnostics, Attributes, Files
 
只对4.0-4.5使用,新版已经抛弃了,可以无视。
一、基于图模型的推荐
在不考虑标签时,基于二项图有两种随机游走的图推荐算法:
1.probability spreading
随机游走算法,在游走中,每个目标得到权重是基于归属者的边计算出来的。
每次传播(item->user->item)后用户Ui的兴趣向量:
2.heat spreading
规则与ProbS相反,在游走中,每个目标得到权重是基于自己的边计算出来的。
每次传播后用户Ui的兴趣向量:
其中:
是节目j的邻域大小,
是用户l的邻域大小。
$a_{ij}$是表示用户i和物品j之间是否有边存在的二元向量。
相比之下,Heats算法倾向于降低热门item的权重,而Probs中与增强对热门item的推荐。
在随机游走算法的基础上,有基于三分图的标签推荐算法:
图中,用户i的每个item的权重(1 or 0)会同时像用户和标签进行传播,这样每次传播后的兴趣向量:
$f_j^t=\lambda f_j^p + (1-\lambda) f_j^{pt}$,其中$f_j^p$和$f_j^{pt}$分别是从(item->user->item)和(item->tag->item)传播后得到的权重。
二、矩阵分解的张量模型
对三元阵$Y_{(n\times m\times t)}$进行矩阵分解,C为核张量,U,I,T为用户特征,物品特征和标签特征矩阵。
根据分解结果对Y进行填充。
填充后即得到评分矩阵
最近在做CTR,刚好Google在KDD发了一篇文章,讲了他们的一些尝试,总结一下:
先是一些公式的符号说明:
[
][1]
一、优化算法
CTR中经常用Logistic regression进行训练,一个常用的Loss Function为
Online gradient descent(OGD)是一个常用的优化方法,但是在加上L1正则化后,这种方法不能产生有效的稀疏模型。相比之下 Regularized Dual Averaging (RDA)拥有更好的稀疏性,但是精度不如OGD好。
FTRL-Proximal 方法可以同时得到稀疏性与精确性,不同于OGD的迭代步骤:
其中$\eta_t$是一个非增的学习率
FTRL-Proximal通过下式迭代:
参数$\sigma$是学习率,一般我们有 ${\sum_{s=1}^t\sigma_s=\frac{1}{\eta_t}}$。
今天收拾资料,发现了以前刚接触粗糙集时写的一个综述,好久没写博客,发上来充数好了
一、粗糙集模型1
粗糙集是Pawlak于上世纪八十年代提出的一种不确定数学模型。该模型以有限集合上的等价关系为基础,定义了上下近似两个基本操作。该模型与它的其他一般化或变种形式有着较为广泛的应用。
Pawlak粗糙集模型是以一个有限集合与集合上的一个等价关系为基础的。所谓的二元等价关系是一种满足自反性,对称性和传递性的关系的二元关系。因为这些性质,一个二元等价关系将一个集合分割成一到多个互不相较子集,形成了集合的一个分割,记为U/R,其中的元素与他们的并被称为精确集。
在这一基础上,Pawlak提出了近似的概念,所谓近似,是通过一个已有集合U的一个分割中的集合的并集对一个U的任意子集X进行逼近,作为X的近似。包括上近似于下近似两种。如,设R是U上一个等价关系,则,X的上下近似分别为:
通过2中近似,我们可以把U分为三个部分,分别称为正域POS(X),边界域BND(X),和负域NEG(X),这三个域都是U/R上一些集合的并,也就是可以用R精确表示的精确集:分别表示一定属于X,可能属于X,和一定不属于X三种定义。
进一步的,对于任意两个等价关系R,D定义:
可以证明的是,在Pawlak粗糙集模型中。
1.2变精度粗糙集模型(VPRT)2
在原有粗糙集模型的基础上,又可以引入变精度粗糙集的概念,变精度粗糙集通过引入一个精度参数,定义
,重新定义正域为
,边界域为
,负域为
。
1.3概率粗糙集模型3
概率粗糙集模型是变精度粗糙集模型的进一步泛化,通过引入两个参数将正域、边界域和负域分别定义为 
。
值得一提的是,这些参数并非一定要考实验者手动选择,有时可以作为数据集的一种性质而导出,比如当我们只有两个X和~X两种结论时,我们可以通过使用成本矩阵中提供的信息对参数进行求解。1
1.4其他粗糙集模型
除了上面提到的3种模型外,还有其他一些模型如模糊粗糙集模型、代数粗糙集模型(如粗糙群、粗糙环)4等,这些模型都是原有Pawlak粗糙集模型的泛化,可以根据不同的需要进行选择。
二、决策粗糙集
决策粗糙集是根据一张决策信息表定义的粗糙集模型,一张决策信息表是一个四元组{U,AT∪D,V,f},其中:
U={u1,u2,u3….} |U|=n<+∞
AT∪D表示属性的集合,分为信息属性AT和决策属性D两个互不相交的子集
通过属性的不同取值,我们可以对U进行分类,而根据AT和D两组属性,我们可以在U上定义两个等价关系,RAT与RD。通过根据这两组划分中的元素的相互关系,我们可以将他们间的元素联系起来,这样我们就得到了一系列的决策规则用于未知数据的预测。
2.1完备信息系统
完备信息系统是指信息系统中U中每个元素ui在AT∪D上的各个属性值确定已知,没有未知或丢失属性的情况发生,对于这种信息表,我们可以简单通过观察属性值是否相同来判断两个元素是否等价。
当信息系统中的属性都是简单的定性分类数据时,我们就可以简单的在U上定义两个等价关系,分别为:
 
通过这两个等价关系,我们得到了U上的两个划分,将U/RAT 中的元素记为pi(i=1,2..|U/RAT|),U/RD中的元素记为qj(j=1,2..|U/RD|),如果有i、j满足集合pi属于集合qj说明当一个元素与等价集合pi中的元素在AT上属性值相等时,就一定有i在D上与qj的元素属性值相等,即可得出一条规则pi->qj。
根据这一思想,我们可以引出更为一般的决策规则。定义信息原子表达式表示满足信息属性ai等于v的所有元素集合。决策原子表达式
表示满足决策属性di等于v的所有元素集合。
现在对信息表达式进行定义,如果是信息表达式则
也都是信息表达式,同时所有信息原子表达式是信息表达式。
同理定义决策表达式,用表示。
用表示规则
中的所有元素属于
。即如果元素满足表达式
,则判断其满足表达式
。这样我们就定义了最一般的规则表达式。
根据粗糙集的正域POS(X),边界域BND(X),和负域NEG(X),我们可以从决策信息表的两个划分中定义以下两种规则
2边界规则:如果,则有:
根据这两种规则,我们就得到了从该信息系统中能得出的有效规则,通过这些规则,我们就可以通过任一元素在AT上的值,去估计它在D上的结论值。
另外,有时我们的属性表中虽然有确定已知的属性值,但可能数据并非简单的定性分类数据,而是定量连续数据,对于这种属性,离散化处理使其变为定性分类数据是最为简单有效的方法。
2.1.2定量属性—相似关系的引入5
有时,我们并不能用简单的定性分类属性表示AT中的所有属性,因此,就引入了另外两种关系:相似关系与优势关系。
当AT中的属性为量化数据时,我们可以简单改变原来属性值完全相等才属于同一类别的定义,对每一个数值定义一个范围的领域,当另一元素y的该属性值属于元素x的该属性的邻域中时,我们就说y与x相似,这样我们就在U上重新定义的一个二元相似关系。
由于邻域可以任意的选择(一般要包括该值自己),所以这一新的二元关系并不一定是等价关系了,这个关系将可能不再满足传递性与对称性。我们用xRy表示x相似于y。根据R对任一个x,我们可以定义两个集合,分别表示相似于x的元素集和x相似于的元素集。
 
这样我们就得到了两个U上的覆盖(由于这个关系将可能不再满足传递性与对称性,U上所有相似类也就不再一定会构成一个U的划分,而是构成一个覆盖。于是我们有覆盖:
有了关系R以后,我们认为一个元素x绝对属于X当且仅当x相似于的元素都属于X,同时,所有相似于X中某一元素x的元素都有可能属于X,于是可以定义U的任意子集X在关系R下上下近似为:
有了这个两个近似后,我们就可以像之前一样计算POS(X),BND(X),NRG(X)并简单的定义信息系统上的两种规则了。
2.1.3优势关系与排序问题
但是当我们决策属不再是简单的分类关系而是一中偏序关系时,我们就不能再像以前一样进行规则的推导了,这是,就要通过引入优势关系下的近似来进行处理。
在优势关系中,在属性集AT上我们定义xDy表示x比y更好,一般来说xDy定义为:
这样,我们就可以对每个x定义两个集合分别表示比x更优的元素和x比其更优的元素。
而处理决策集时,我们不再简单对每一类决策类求近似,而是求他们并集的近似:
有了这四种近似后,我们可以将(1)(2)分为一组,(3)(4)分为一组,分别按照原有方法导出两种规则求解一定属于的元素规则和可能属于
的元素规则。
2.1.4成对比较表法PCT6
当我们拥有一张已经排序的信息表时,除了以上提到的方法以外,还有一种成对比较表法可以处理排序问题,导出规则对未知元素进行排序。
该方法的核心是将原来定义在U上的信息表扩展为一个UXU上的信息表。
新的信息表表示为{UXU,AT∪D,V,f}}
UXU: |UXU|=n*n
AT∪D中的属性与原有信息表中的属性一一对应,但是不再表示具体的属性值,对于AT中的属性a和元素(x,y),新的信息表中a的值表示在原信息表中元素x比y在属性a上的优异程度。而对于D中的属性值,新的信息表中的属性d仅表示x优于y或y优于x。

