







Arthur Samuel (1959). Machine Learning: Field of study that gives computers the ability to learn without being explicitly programmed.
使机器在没有明确编程上的研究领域具备学习的能力.
Tom Mitchell (1998) Well-posed Learning Problem: A computer program is said to learn from experience E with respect to some task T and some performance measure P, if its performance on T, as measured by P, improves with experience E.
对于某类任务T和性能度量P,如果一个计算机程序在T上以P衡量的性能随着经验E而自我完善,那么我们称这个计算机程序在从经验E学习.
完全为了押韵…
如图片所示,监督式学习为right answers given.
.此处为regression(回归模型)
.
Regression: Predict continuous valued output(price)
回归: 预测一系列的值输出(价钱)
此处为Classification(分类模型)
,
Classification: Discrete valued output(0 or 1)
分类: 分离值输出(0或者1)
代价函数: 与真实的所表现出来的误差函数.
强烈建议阅读:深入浅出-梯度下降法及其实现
略.
之前一直很好奇像sanic或者aiohttp是如何实现并发的,其实从网上看无非就是使用了asyncio,更底层就是事件驱动,libevent之类的,但是纯从应用层来讲,这个会是怎么一回事呢,举个例子:
1 |
|
从上面代码来看,整个执行周期为3s,但是有个问题是:如果请求一个一个来,如何不阻塞呢??
1 |
|
如果按照例如eventlet的做法:
1 | procpool = GreenPool(size=poolsize) |
消息过来,直接抛给pool,并不会进行阻塞,并且有poolsize控制池大小,
额,这里是sanic源码中的一部分…
1 | # -*- coding: utf-8 -*- |
目前在开发的内部爬虫框架中,对于从消息队列中取任务部分,如下图所示,遇到了一些问题。
因为我们整个模型为async的,底层使用的asyncio,对于消息队列的客户端来讲,可选择有的pika和kombu,对于kombu,的确是一个不错的选择,相比pika callback的写法,的确封装的更为高级,写起来比较方便,另外官方支持与eventlet工作,例如openstack的nova底层使用的就是eventlet与kombu,但是kombu目前不支持asyncio,官方将于5.0版本提供支持,我很看好,题外话。
那么目前能够选择貌似只有pika了,官方示例,奈何实力不高,只能在callback的基础上加代码,此处分成两个版本,如下所示。
1 |
|
异步取来的任务,将其抛给线程池/进程池处理,那么上层应用者直接在get_list
和get_data
中进行处理,那么此处就有非常大的问题了,因为一个好好的异步模型活生生的给改成了有点同步的感觉了,如果我想在业务层执行异步任务,会发现在当前线程中无法get eventloop,哈哈,好尴尬。这点实际在tornado官方文档中描述如何执行同步代码中有提示,是不是和这个很类似.
1 |
|
上面的实在受不了,太烂了,所以此处还是要想办法给异步了,此处斜眼。
此前在看nameko中消费者处理时,他是使用eventlet.spawn方法开启一个新的协程进行处理,从而不阻塞当前loop,那么在asyncio中也一定有相应的方法,下面出场asyncio.async和asyncio.ensure_future方法,其实也是一个方法,asyncio.async将被放弃啦,所以所以介绍ensure_future方法。
1 |
|
由于使用的pika连接器是asyncio的,那么根据pika的官方文档描述,获取到的任务只有在完成的时候才会进行下发新的任务,
如果如上get_list
方法下面的使用者写的是同步代码,会导致效率非常地下,所以此处会强制提升业务代码至异步模型,貌似有点激进,所以暂时不更新.
额,几天没有更新了,经过几天的思考,目前采用多线程/多进程模型,为什么没有使用异步呢?我觉得可以从一下几方面总结:
先把第一个版本做稳定了,因为目前还是有一些问题的,因为分布式爬虫框架,程序异常退出以及退出迟迟没有在server端看到客户端下线,还要定位原因以及加强处理,等稳定后再加入timer等其他功能。
1 |
|
1 |
|
但是今天将介绍另外两种不同的写法,而这两种写法也在库中比较常见
1 | class App(object): |
为什么叫flask-like呢?因为我也没有想到好的名字来叫,另外这种写法也是在flask中见,因为他没有包装func(*args, **kwargs)这层,而是仅给func传递参数.
1 |
|
今天在同事的推荐下,看了下扇贝的sea代码,
没细看,突然看到了cached_property
的代码,这个让我突然想到了我们内部爬虫框架的cached_property
,当时我在写这部分代码的时候主要目的有点类似如下:
1 | class A(object): |
A
为一个类,然后B
有点类似A
的一个超集,平常使用的使用为实例化B
, 然后为了操作A
下面的方法,基本流程为:
1 | >>> b = B() |
当时设计的时候,并没有想到通过property这个将方法变成属性的方法,当时想我只需要初始化两次就行,如下:
1 |
|
但是后来我就意识到我这种设计有点low,因为其他同事调用的时候可能不会这么使用,另外因为B
下面还会有其他类似A
这种东西,例如:
1 | class B(object): |
难道每次使用的时候都拿到c这个实例吗,有点傻,所以参考了Flask
的cached_property
实现,改成了如上了流程.那么进入主题,cached_property
到底干了什么事情?
先看Flask
的实现:
1 |
|
再看sea
的实现:
1 |
|
唯一不同点应该就在于加了一个锁吧,那么抛去锁的部分,单纯讲cached_propery
的实现
1 |
|
学过Python的应该蛮清楚关于装饰器这个概念,当将cached_property加在b上时,就已经完成了cached_property类的实例化(看最后一个类版本的计算时间装饰器),那怎么传进去的呢?
1 |
|
调用的时候怎么个过程?看Python Document
1 | class Property(object): |
1 | def __get__(self, instance, cls=None): |
1 | class B(object): |
剩下自行理解吧..
1 | # 类版本的计算时间的装饰器 |
这里说的 AdjacencyList , 就是最常用来在关系数据库中表示树结构的,parent
方式:
id | name | parent |
---|---|---|
1 | 一 | null |
2 | 二 | 1 |
3 | 三 | 2 |
上面的数据, 表示的结构就是:
一
|- 二
|- 三
模型定义很好做:
1 | # -*- coding: utf-8 -*- |
这里不让parent
字段有null
, 而使用0
代替.
这个例子在关系上, 有一个纠结的地方, 因为 node
这个表, 它是自关联的, 所以如果想要children
和 parent_obj
这两个关系时:
1 | children = relationship('Node') |
呃, 尴尬了.
如果是两个表, 那么 SQLAlchemy 可以通过外键在哪张表这个信息, 来确定关系的方向:
1 | class Blog(BaseModel): |
因为外键在 Blog
中, 所以 Blog -> User
的 user_obj
是一个 N -> 1
关系.
反之, User -> Blog
的 blog_list
则是一个 1 -> N
的关系.
而自相关的 Node
无法直接判断方向, 所以 SQLAlchemy
会按 1 -> N
处理, 那么:
1 | children = relationship('Node') |
这两条之中, children
是正确的, 是我们想要的. 要定义 parent_obj
则需要在 relationship
中通过参数明确表示方向:
1 | parent_obj = relationship('Node', remote_side=[id]) |
这种方式就定义了一个, “到 id” 的 N -> 1
关系.
现在完整的模型定义是:
1 | class Node(BaseModel): |
查询方面没什么特殊的了, 不过我发现在自相关的模型关系, lazy
选项不起作用:
1 | children = relationship('Node', lazy="joined") |
都是无效的, 只有在查询时, 手动使用 options()
定义:
1 | n = session.query(Node).filter(Node.name==u'一')\ |
如果要一次查出多级的子节点:
1 | n = session.query(Node).filter(Node.name==u'一')\ |
多个 joinedload()
串连的话, 可以使用 joinedload_all()
来整合:
1 | from sqlalchemy.orm import joinedload_all |
在修改方面, 删除的话, 配置了 cascade
, 删除父节点, 则子节点也会自动删除:
1 | children = relationship('Node', lazy='joined', cascade='all') # 1 -> N |
如果只删除子节点, 那么 delete-orphan
选项就很好用了:
1 | children = relationship('Node', lazy='joined', cascade='all, delete-orphan') # 1 -> N |
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true