c/c++利用libpq读取postgresql

没办法,有些c系场合不适宜用.Net/Java之类,尽管有胶水python,但其c/c++的扩展方式确有许多蛋疼之处,所以不如直接上马。相对与mysql哪怕sqlite之辈,postgresql在c接口上维护地非常好,但是却极其低调。尽管之后由libpqxx,但其trac站点似乎总是有问题,版本也没有一直在维护。因此使用自带的libpq是相对明智的选择。

由于在OSX下,本地一直用的postgresapp,而非官方安装包,因此lib或include的安装路径当然与官方文档上不一致,而是都在Postgres.app的包里边:

Default data directory: ~/Library/Application Support/Postgres/var-9.3
Binaries: /Applications/Postgres.app/Contents/Versions/9.3/bin
Headers: /Applications/Postgres.app/Contents/Versions/9.3/include
Libraries: /Applications/Postgres.app/Contents/Versions/9.3/lib
Man pages: /Applications/Postgres.app/Contents/Versions/9.3/share

不是很勤快,所以用的还是9.3。显而易见地,我们需要告诉编译器如何include头文件和link必须的lib,因此g++需要知道这些参数:

-I /Applications/Postgres.app/Contents/Versions/9.3/include -L /Applications/Postgres.app/Contents/Versions/9.3/lib -lpq

然后就是代码了,必须承认,写惯了python的人真的受不了如此繁琐的写法,但严谨些至少让人萌生敬意。下面用个简单官方sample简单改了一个例子:

稍显怪异,习惯了就好。

隐马尔可夫模型的基本概念

自然语言处理领域,隐马尔可夫模型在语音识别、词性标注、分词等方面都有不少研究和应用。

对于一个典型的HMM示意图(图来自维基百科:隐马尔可夫模型)如下:

Hmm

在正常的马尔可夫模型中,状态对于观察者是直接可见的,因此状态的转换概率即是参数。而在HMM中,状态(x)不是直接可见的,但每个状态下输出的某些输出(y)是可见的。每个状态在可能输出的符号上都有一个概率分布(b),即(符号)输出概率-(symbol)emission probabilities。另外,少不了隐含状态间的转换概率(a),即transition probabilities。由此可见5大要素:

X — 隐含状态集合
Y — 可观察的输出集合
A — 转换概率
b — 输出概率
π — 初试状态的概率分布

其中,π和A决定了状态序列,且这里用到马尔可夫假设,即当前隐含状态只取决于前一个隐含状态。而B决定了观测序列。所以一般认为隐马尔可夫模型λ可以用三元符号表示:

 lambda =left( A,B,pi right)

关于如何理解隐含变量以及HMM的大致原理,好的文章太多了,其中简单易懂的,我觉得这条知乎上Yang Eninala的回答写的很有耐心。

统计自然语言处理的基本概念

NLP的几个层次

以下是学习宗成庆著作中相关内容整理,详细内容可参考其著作《统计自然语言处理》。自然语言的处理包含语音、形态、语法、语义、语用几个层面,若暂不考虑语音和语用,以下三个概念非常重要:

形态学(Morphology)

词汇形态学(或词法)研究词的内部结构。

语法学(Syntax)

研究句子结构元素之间的关系与规则。主要关注一句话该怎么讲。

语义学(Semantics)

研究语言各级单位(词素、词、词组、句子、句子群、整段整篇、甚至整个著作)的意义,重点是研究符号与符号所指对象之间的关系。

NLP的基本方法

自然语言处理真的很困难,词汇形态歧义消解并不容易。有研究结论称,歧义结构分析结果的数量随介词短语数目的增加呈指数上升的,其歧义组合的复杂程度随着介词短语个数的增加而不断加深,这个歧义结构的组合数目称为开塔兰数(Catalan numbers),下式中,n为介词短语个数:

c_{n}=left( begin{matrix} 2n\ nend{matrix} right) dfrac {1} {n+1}

上面讲的是英文情况,中文自然语言里,各种歧义、指代等,也是相当的复杂。对于这些复杂问题的理解,存在两种不同的“主义”,即理性主义方法和经验主义方法。

理性主义方法

理性主义方法的代表是著名的乔姆斯基理论,认为人的语言能力是与生俱来的。因此对于NLP的难题,需要首先由词法分析器按照人工编写的词法规则对输入的句子的单词进行词法分析,然后根据人工设计的语法规则对输入的句子进行句法结构分析,最后再根据一套变换规则将语法结构映射到语义符号(如逻辑表达式、语义网络、中间语言等)。

经验主义方法

经验主义认为,人(孩子)的大脑一开始具有一些基本的处理能力(联想、模式识别、通用化),因此可以在后期通过感官输入来不断学习和掌握自然语言的结构。因此在实践层面,经验主义方法主张通过建立数学模型来学习语言结构,然后利用统计学、模式识别和机器学习等方法来训练模型的参数,以扩大语言使用的规模。从方法上看,经验主义的思路是很明确的统计自然语言处理(SNLP)方法。

统计方法中的基本概念

统计方法中,概率论和信息论是最基本的部分,必须掌握地相当靠谱才行:

  1. 概率论基本概念:概率、条件概率、贝叶斯法则、贝叶斯决策理论、随机变量、参数估计方法、二项式分布、联合概率分布和条件概率分布、期望和方差等。
  2. 信息论基本概念:熵、联合熵、条件熵、相对熵、交叉熵、互信息、困惑度、噪声信道模型等。

 

时空平稳性的概念与STARMA模型

时空相关性

时空相关性反映了序列对时空的依赖,一般会讨论到时空自相关性和时空偏相关性两个概念。

时空平稳性

时空平稳性(Space-time Stationarity)的概念,是说如果是平稳的,那意味着在时空范畴内不存在任何趋势或者模式。在统计上,表现为均值、方差、协方差等不随时间和空间的变化而变化。在实际应用中,很少能够满足统计上绝对的不变值,因此只要求近似为常数即可认为时空序列平稳。

因此,对于时空平稳的时空变量来说,

时空非平稳性,可能是大尺度的趋势,也可能是局部效应。

  1. 大尺度的非平稳:描述均值的总体变化。通常称为“一阶”效应。
  2. 局部的非平稳:是对时时空相关局部特征的描述。通常称为“二阶”效应。对于时间序列分析,一般用自相关移动平均描述因时间依赖造成的局部效应;对于空间数据分析,一般用空间自相关描述其局部效应。

STARMA模型

严格说来,STARMA模型是由时间序列模型模型ARMA(自回归-移动平均)向空间层面扩展而来。该模型在时间序列的基础上,增加考虑了空间相邻位置的影响,因此从时空结合角度讲,更为准确。模型有两个基本假设:

  1. 序列是平稳的
  2. 随机误差符合正态分布

因此,随之而来的处理方式中,首先要解决序列的平稳化问题,过程中需要通过观察空间自相关系数来发现非平稳的存在,并可能会用到各种手段来实现平稳化,例如进行周期性差分处理。

如何给nexus 5/6 刷上Android M preview 2

官方时间表

尽管不久的七月底应该就出第三个preview了,还是忍不住当了回小白,把nexus6刷成android M了,没有尝试nexus5,但就网上资料看,情况大致一样。首先看下google官方的timeline吧,传说中的M第三季度即将正式到来。

enter image description here

下载image文件

目前为止preview2的下载位置是这里。选择合适的版本,比如nexus6是shamu。

enter image description here

解压下载包后,里边的东西是这样的:

enter image description here

bootloader和radio的文件名跟设备和版本有关。image-shamu-**.zip压缩包里是这些东西:

enter image description here

刷入步骤

android developer网站上有详尽的指南,原本按照这些步骤,应该就衣食无忧了。但实际上fastboot工具没法直接找到image-shamu-MPZ79M下的几个img文件,很明显flash-all脚本写的不够人性化。网上有修改该脚本的讨论,没有仔细去研究,因为手动操作几下总体上比较省时间。参考网上的这篇文章后,大致的操作步骤变更为如下:

  1. 将android-sdk下的platform-tools文件夹添加到操作系统的PATH变量里(例如osx下可写入~/.bash_profile文件),主要是要让flash-all脚本能用到。
  2. 进入开发者模式,确保usb调试状态打开;确保OEM可解锁。
  3. 进入fastboot模式,命令行:adb reboot bootloader。此时小机器人画面会出现。
  4. OEM解锁(以后可以在lock回去):fastboot oem unlock。此处手机上需要确认YES or NO,按提示操作。
  5. 命令行执行flash-all.sh(osx下./flash-all.sh),按照官方指南,此处应已万事大吉。可实际情况的确会出现一堆ok,直到出现某个image缺失,那就是没有找到image-shamu-MPZ79M中的内容了,于是逐个加载,注意是有顺序的。所有都执行完后,fastboot reboot一下。逐个加载过程如下:

其间,只有system.img的导入会稍微耗时一些:

ok,就是这样了。

空间权重矩阵(SWM)

基本原理

如何利用数学(如用面积、距离等)建立空间数据和非空间数据之间的关系?对于空间统计而言,空间权重矩阵是一种有效的表达空间关系的方式。因此,它是用量化的方法表示了数据之间的“空间结构”。

关于如何进行要素间实际交互方式的概念化,ESRI举出的例子:

如果要测量森林中某种特定种类的种子繁殖树种的聚类,使用某种形式的反距离可能最适合。但是,如果要评估某一地区通勤者的地理分布,行程时间和行程成本可能是更好的选择。

空间权重矩阵是N*N的表,N为数据集中的要素数量。因此给定行列组合后,其对应的值即为权重。这种空间关系的权重矩阵在许多空间统计工具里都有用,比如空间自相关、热点分析、聚类和异常值分析等。

创建策略

  1. 二进制策略:某个要素要么是邻域-1,要么不是-0。例如:固定距离、K 最近邻域、Delaunay 三角测量、邻接或空间 – 时间窗口。
  2. 权重策略:邻近要素有不同量级的影响,并通过计算权重来反映该变化。例如:反距离或无差别的区域。

工具使用

arcgis中的SWM使用稀疏矩阵存储,因此只存非零部分。实际情况,每个要素一般只跟其他某几个要素发生关系。

工具名字:Generate Spatial Weights Matrix (Spatial Statistics),工具界面如图:

SWM的使用:以热点分析为例

具体权重的使用,以热点分析为例,几个主要的步骤如下:

integrate与collect event

collect event的结果数据

重点是需要生成feature class,并且确保这个feature class有一个唯一id字段。

Generate Spatial Weights Matrix

Hot Spot Analysis (Getis-Ord Gi*)

使用gunicorn来部署django应用

第一次注意到gunicorn这个django部署工具是在instagram的技术报告里,主要吸引我的地方就两个:

  1. 部署与扩展都非常容易
  2. 与nginx集成良好

下面实际的记录可能包含gunicorn和django以外的其他软件包的安装,是我顺手记录下得,基本环境并不包含这些。

准备工作

1.安装django

python不说了,linux基本自带。django可以向下面部分一样选择使用easy_install或者pip来安装,但是在我的环境下pipy的服务器下载django非常的慢,经常连不上,因此还是下载源码安装: 目前的版本是Django-1.6.1

cd到解压目录,执行:

2.django项目运行的依赖项

依赖项主要是数据库,以及django有关的各类插件或模块,以我自己的部署为例:

PostgreSQL

我的django使用PostgreSQL为主要数据库,所以这个逃不掉。下载与安装说明请戳这里。尽管有种种不建议,我还是使用了官方提供的Graphic Installer

psycopg2

PostgreSQL的python语言接口

空间数据支持

由于依赖PostgreSQL的空间数据扩展PostGIS,而读写空间数据需要其他额外的库资源。因此,安装完具体需要安装:

  • GEOS
  • PROJ.4
  • PostGIS

这个在OSX、Linux和Windows环境下差异较大,具体查看官方文档的说明

3.安装gunicorn

下载源码安装

由于生产环境和开发环境不一样,实际上我用到了如下两个:

easy_install安装

pip安装

让gunicorn跑起来

1. gunicorn命令方式

gunicorn_django的写法

如果不指定[SETTINGS_PATH],将在当前文件夹查找settings.py。

gunicorn的写法

根据官方文档的提示,建议Django1.4以上版本,直接使用gunicorn命令,而不是gunicorn_django命令,在这里暂时不去追究原因。

其实很简单,cd到manage.py所在目录,从wsgi所在app启动(我的app叫mserv)。

这就是纯WSGI写法。现在再多写一点,绑定ip和端口:

好了,可以在客户机上查看你的服务了。那么可以再多一点点,多一个工人帮你搬东西,会快一些:

这样启动的时候你会看到两个worker:

多么体贴!

更多命令参数可看官方文档的Settings部分

2. django manage.py方式

好吧,确实有更简单的方式,我们真的可以使用django的manage.py来跑gunicorn服务,我叫它植入式。

首先修改django的settings.py:

然后命令行到django项目目录,可以做很神奇的事情:

小结

这是一个功能强大、易于配置的,对django友好的部署环境,这里是一个开始。个人而言,后面可以讨论的内容包括但不限于:

  • 性能测试与参数调优
  • 与nginx部署环境的整合
  • 合理处理消息,研究真实生产环境中如何管理服务
  • 对gunicorn运行状况的监控
  • 整合django的自动化部署

为什么使用django

使用django的缘由

很多事情在开始之初,一般很难会有绝对成熟的理由和卓越的趋势判断。因此当初选择django入手,主要只是出于这么几个考虑:

  1. 后台需要更敏捷些。这也是python一早就映入了我的眼帘的原因,也是出于对现有后端平台开发状况的不满。当前团队主要在使用的后台开发技术已经积累地比较成熟,能够很好地满足项目的需要,但未必适合轻量级甚至创新型应用的推进。或框架过于庞大,或组织过于凌乱。希望能够有一个平台能够介于两者之间,并且最好是可控的。
  2. 不重复造轮子。其实python的世界里从来不乏好的框架,不同框架之间的优劣争论也四处可见也从未见过可靠的结论。我的看法是,适用即可。对于综合性非常强的gis类应用,我不希望在基础架构上耗费太多的精力。django是一个考虑周详的框架,从ORM到admin管理工具,他思考了几乎所有的主要问题。
  3. 适度可控。尽管我不造轮子,但是如果轮子出现什么问题,我依旧能够对他进行改造,哪怕是打补丁,来满足我的需要。django是一个开源软件,并且代码组织良好,发展多年来一直比较稳定,在国外也拥有相当的用户基础,虽然一度被职责不够灵活,但是在我看来,框架与灵活本就是一堆矛盾,只在于供需一致性。

开始尝试

万事开头难,我一直希望在繁忙中可以逐渐积累出一个app的雏形,以供多个方向参考发展只用。这可以是个不太复杂的应用,但必须适用并且贴合实际。这个有点难,因为每个人的行为和理想很难完全保持一直。但是好在我们有不错的机会推动,以至于app很快就从零开始产生。

起初,django扮演的角色并不复杂。我们需要一个用户管理环境,包括用户的增删改查和图层权限分配。django的user管理模型能够适应大多数初级需求,并且我们没有多余的人手去改造以前的技术平台,因此,就这么开始了。

orm、auth、session与admin

这几个轮子都是django的重要组成部分。

orm机制解放了大多数对关系数据库的操作,尤其是对关联表的操作;另一个好处是会强迫自己更加重视设计。即便是对于初学者,一而再、再而三的修改model,对于操作来说,毫无压力。

和一般应用的主要的区别,需求并不是在做一个网站,而是一个iPhone app。这要求我从一开始就要熟悉django的用户管理机制,并且尝试改造它。auth和session模块是django中相当成熟的部分,主要考虑的,是和iOS的native app的整合程度。坦白讲,这种做法还太小众,但是stackoverflow已久可以找到一些资源。

我们确实需要不同的管理员角色,来管理部分数据表,比如地图图层的管理——admin是一个非常理想的工具,他解放了双手,提供了一个不算太优雅,但也不是很差的model到可编辑表格的转换,可以满足使用。当然,有不少其他爱好者的工具,比如类似xadmin的对admin的梅花替换。

并不完美,但有助于协作

起初独立来完成这些工作,实属无奈,没有多余的人手,熟悉python框架的人更少。但是长远看,python严谨的语法,和django古板、保守的设计,一定程度上有助于后期的多人协作。尤其是project到apps的模块化分解,可以做到淋漓精致,这个目前还在实践中慢慢完善。

信息化项目管理之罪

信息化项目不需要讨论业主方,他们的目的其实说起来也单纯,就是要把事情做好,让有所希冀的人都能满意,这些都是对的。至于监理方和承建方,似乎命中注定是互掐。作为践行者的一方有时候需要装作傻子,作为协管的一方需要斡旋,大家其实都很累。

需求在项目实施过程中完成,似乎是中国信息化项目建设的一大特色。运作的好的,还是会在“实施阶段”的时间里按序完成好需求、设计、实施……等环节。倘若出现意外,可能这些缓解从项目开始到项目结束都一直混杂。这其实并不可怕,有心有力有理,还是可以做好。

最苦逼的事情莫过于需求没定就被要求列计划,过程中需求变化导致实施不能按计划走,却被要求走计划变更流程。大家都是学过项目管理,搞技术的对于项目管理基本常识还是有的,需求变更从来不走,需求蔓延从来不主动控制,此类监理原本不要也罢。却还真真是个监督不讲理又甩不走的主,表上扯不开领导面子,心里搁不下延期欠费的担忧,压力频往承建方甩。

与食品安全问题如出一辙,冠冕职业道德与法理却固偏邪之行径,与禽兽何异?此乃我天朝现状与悲哀。只想起一句话,这句话最近因为《云图》而再次被人们记起:“我绝不会向暴力犯罪屈服!”倘若人心依旧向善,希望10年后有所改观。

django如何处理request

当用户请求页面时,系统的算法会选择哪一个python代码会被执行:

1、检查root URLconf模块,一般来说,这个值是ROOT_URLCONF设置,但是如果HttpRequest对象有一个叫做urlconf的属性(通过request processing这个中间件进行设置),这个值就会替代ROOT_URLCONF的设置。
2、Django加载那个python模块,并且查找urlpatterns这个变量,这个变量是一个python list,遵循函数django.conf.urls.patterns()返回的格式。
3、Django按顺序执行每一条URL pattern,然后在第一条与请求的url相匹配的记录处停下。
4、一旦某一个正则表达式匹配了,Django imports并且调用所给定的view(一个简单的python函数)。这个view将HttpRequest作为它的第一个参数,然后从正则表达式中捕获的其他值作为剩下的参数。
5、如果没有表达式被匹配,或者在任何环节由异常被出发,django将出发一个适当的错误处理视图(error-handling view)
当然,也可以使用python的制定参数名的方式。
内容来自官方文档