python下的c/c++扩展方式详解

python作为一种胶水语言,最重要的是非常容易的和shell,c/c++之间进行相互扩展,而本文主要是对python的c/c++扩展进行详细讲解,并作为笔记便于以后的使用。 为什么要进行c/c++扩展python之所以使用广泛,主要是因为使用简单,第三方扩展库强大,对于某个问题,能迅速的验证自己的思路或某个原型。但是,python的效率是比较低的,因此很多涉及到效率的时候需要使用c/c++来实现,为python提供接口即可。这样混合编程后,能达到快速+效率的双重目的。 python的c/c++扩展在python下的c/c+扩展有很多方式,主要有cffi/ctypes,cpython和cython这几种方式,各个方式都有优势。下面对这几个方式进行详细的说明。 cffi来进行c扩展cffi是连接c和python的桥梁,是在pypy中分离出来的一个库,这个和python自带的ctypes模块很相似,但是cffi更加通用。下面我们定义了一个pi.h和pi.c文件: // file: pi.h #ifndef C_EXTEND_PYTHON_PI_H #define C_EXTEND_PYTHON_PI_H float pi_approx(float n);#endif *//C_EXTEND_PYTHON_PI_H* // file: pi.c float pi_approx(float n){ return 3.1415926 * n * n; } 使用cffi模块来对这两个文件进行编译,会生成一个c source文件和.so或.pyd文件,可以在python下直接引用,进行使用,编译文件如下: from cffi import FFI ffi_builder = FFI() ffi_builder.cdef(""" float pi_approx(float n); """) # This describes the extension module "_pi_cffi" to produce. ffi_builder.set_source("_pi_cffi", """ #include "pi.c" // the C header of the library """, libraries=[]) # library name, for the linker if *__name__ == "__main__": ffi_builder.compile(verbose=True ) 直接运行该编译文件则可创建python的c扩展库:.so或.pyd文件;另外也会生成_pi_cffi.c的源码。将.so或.pyd文件放如对应的目录即可实现引用。这种方式比较方便,能迅速构建c扩展。...
 2019-04-18   Python    c/c++  numpy  cython  优化  compile 

多级网络优化的规划问题简化-Python预演

背景和目标在物流网络中,经常存在需要优化的网络结构,比如从生产中心到一级仓库 ,到二级仓库再到配送中心,这样形成一个多级的分仓体系。在实际执行过程中会遇到DC层或TC层的选址问题,一般会遇到优化问题,优化的目标主要考虑多个方面的成本,如运输成本,仓库成本,转运成本等等。如果按照多级网络的模式进行考虑,一般规划问题会成为非线性的整数规划问题,在求解上是非常难且建模也比较难。 现在对于这样的其中选址的问题进行思考:假设我们只是考虑运输成本或距离上的成本,DC层的仓库可以向周边的仓库进行供货,而且保证TC层的一个仓库只能唯一的DC层仓库供货。从常规的建模一般都是在DC层设置一个变量X, TC层设置一个变量Y,来计算目标,并设置约束,最终来进行求解,那么这个问题能简化么? 如果能简化那么这个问题就能推广到多层的选址问题,不需要非线性整数规划的方式进行求解。能大大的简化整个求解,可能不是最优的解,但是能得到较优的解。经过仔细的实验和思考,是能进行简化的。将DC层和TC层的地址看为一个变量,这样就减少一个变量,转化为了线性规划的问题(LP)。DC层对TC层为1对N的方式,但是TC只能属于一个DC。而且可以控制DC层的地点或TC层的地点的个数。解决了选址中遇到的所有问题。 数据的准备这里我们准备了一些城市的数据,其中有DC,TC层和最终的地点。数据存储于mysql数据库中,下面定义一个数据抽取的class,来进行数据查询,并生成需要的距离矩阵。便于后续使用该矩阵来进行优化目标值的计算。...
 2019-04-11   思考    Python3  思考 

KL散度,JS散度和wasserstein距离

最初了解信息度量是通过熵的概念,比如信息增益,GINI等都是基于熵。而这三者也是基于信息熵,在信息论中主要对分布的相似度(距离的度量),但是三者差异性也是很强的;对这三种信息度量的方式进行详细的说明。 1.KL散度KL散度又称为相对熵,信息散度,信息增益。KL散度是是两个概率分布P和Q 差别的非对称性的度量。 KL散度是用来 度量使用基于Q的编码来编码来自P的样本平均所需的额外的位元数。 典型情况下,P表示数据的真实分布,Q表示数据的理论分布,模型分布,或P的近似分布。在之前了解KL散度的时候也写过KL散度的博文. DL(p||q)=\sum_{i=1}^{n} p(x) \log{\frac{p(x)}{q(x)}}KL散度性质: 因为对数函数是凸函数,所以KL散度的值为非负数。 KL散度不是对称的。 KL散度不满足三角不等式。 2.JS(Jensen-Shannon)散度JS散度度量了两个概率分布的相似度,基于KL散度的变体,解决了KL散度非对称的问题。一般地,JS散度是对称的,其取值是0到1之间。定义如下: JS(P_1||P_2)={\frac {1} {2}} KL(P_1 || \frac {P_1+P_2} {2})+{\frac {1} {2}} KL(P_2 || \frac {P_1+P_2} {2})如果P1,P2完全相同那么JS散度的值为0,否则为1. JS散度的时对称的而且是有界的[0, 1]。在深度学习中的GAN网络中会有JS散度的概念。 KL散度和JS散度度量的时候有一个问题:如果两个分配P,Q离得很远,完全没有重叠的时候,那么KL散度值是没有意义的,而JS散度值是一个常数。这在学习算法中是比较致命的,这就意味这这一点的梯度为0。梯度消失了。...
 2018-11-24   机器学习    GNN  deep learning  KL散度  JS散度  Wasserstein 

深度学习-GAN网络详解及TensorFlow实现

GAN的基本介绍2014 年,Ian Goodfellow 及其蒙特利尔大学的同事引入了生成对抗网络(GAN)。这是一种学习数据的基本分布的全新方法,让生成出的人工对象可以和真实对象之间达到惊人的相似度。 基本概念GAN(Generative Adversarial Networks),是一种生成式的,对抗网络。再具体一点,就是通过对抗的方式,去学习数据分布的生成式模型。所谓的对抗,指的是生成网络和判别网络的互相对抗。生成网络尽可能生成逼真样本,判别网络则尽可能去判别该样本是真实样本,还是生成的假样本。示意图如下: 基本原理生成器和判别器两个网络彼此博弈,目标是生成器生成与真实数据几乎没有区别的样本。生成器$G$的目标是基于噪声变量$z$生成一个对象$x^{‘}$,并使其看起来和真的$x$一样。而判别器$D$的目标就是找到生成出的结果和真实$x$之间的差异,差异越小越好。如上图所示。隐变量$ z $(通常为服从高斯分布的随机噪声)通过 Generator 生成 $X_{fake}$, 判别器负责判别输入的 data 是生成的样本 $X{fake}$还是真实样本 $X\{real}$。通过公式描述如下所示: \min _{G} \max _{D} V(D, G)=\mathbb{E}_{\boldsymbol{x} \sim p_{\operatorname{tat}}(\boldsymbol{x})}[\log D(\boldsymbol{x})]+\mathbb{E}_{\boldsymbol{z} \sim p_{\boldsymbol{z}}(\boldsymbol{z})}[\log (1-D(G(\boldsymbol{z})))]对于判别器 $D$ 来说,这是一个二分类问题,$V(D,G)$ 为二分类问题中常见的交叉熵损失。对于生成器 $G$ 来说,为了尽可能欺骗 $D$,所以需要最大化生成样本的判别概率 $D(G(z))$,即最小化 $log(1-D(G(z)))$,注意:$log(D(x))$ 一项与生成器 $G$ 无关,所以可以忽略。 实际训练时,生成器和判别器采取交替训练,即先训练 $D$,然后训练 $G$,不断往复。值得注意的是,对于生成器,其最小化的是$\max\ _{D} V(D, G)$,即最小化$V(D,G)$ 的最大值,这样形成一个对抗的过程。...

TensorFlow中的KeyPoint

1.线程,队列和流水线在TensorFlow中也会使用线程和队列,主要在模型开始训练时对数据的处理时,通过多线程来读取数据,一个线程来消费数据(模型训练)。在TensorFlow中的线程主要通过Coordinator和QueueRunner来进行配合管理,队列Queue主要有四种队列。 一句话概括就是:Queue->(构建图阶段)创建队列;QueueRunner->(构建图阶段)创建线程进行入队操作;f.train.start_queue_runners()->(执行图阶段)填充队列;tf.train.Coordinator() 在线程出错时关闭之。 1.1 线程管理-CoordinatorCoordinator类主要对多线程进行同步停止。它和TensorFlow内的队列没有必然关系,可以和python的线程(threading)配合使用。Coordinator类主要有三个方法: tf.train.Coordinator.should_stop:如果线程停止,则返回True。 tf.train.Coordinator.request_stop:请求线程停止。 tf.train.Coordinator.join:等待直到指定的线程停止。 在使用Coordinator时,首先创建一个Coordinator对象,再创建一些Coordinator使用的线程。线程通常一直循环运行,直到should_stop()返回True时停止。任何线程也可以被请求停止,只需要Coordinator对象调用request_stop方法,调用该方法时,其他线程下的should_stop都被返回为True,其他线程停止。如下,通过Coordinator管理python的线程: # -*- coding: utf-8 -*- import tensorflow as tf import threading def thread_func(coord, id_num): """ :param coord: tensorflow Coordinator object. :param id_num: int, the constant number :return: id_num, int """ while not coord.should_stop(): print("This thread id is %d" % id_num) if id_num >= 9: print("Stop thread id is %d" % id_num) coord.request_stop() # init coord object coord_object = tf.train.Coordinator() # create 10 threads and run thread function threads = [threading.Thread(target=thread_func, args=(coord_object, num)) for num in range(10)] for t in threads: t.start() coord_object.join() Coordinator还支持捕获和报告异常,如try:.......except Exception as error: coord.request_stop(errr) finally: coord.request_stop()。...

深度学习-详解CNN网络和TensorFlow实现

1. 卷积神经网络概述卷积神经网络(Convolutional Neural Network, CNN) 也是神经网络中的一种结构,主要针对图像,音频,视频等方面应用。卷积神经网络较早的架构是LeNet,被认为是CNN的开端,当时主要将LeNet应用于字符识别任务,如手写数字的识别等。下面是一个LeNet的网络结构: 1.1 CNN的一般结构从上面LeNet的结构中基本可以看出,CNN的大体结构:卷积层(一个或多个,包括ReLU操作等),池化或者亚采样,分类(全连接层)几个部分组成。每个部分当然有很多细节的地方。比如卷积是如何计算,卷积核的定义等;池化操作的方式,计算方式等。但CNN模型一般都会存在这几个组件。下面对一些名词进行解释,便于后面的理解: 通道:常用于表示图像的某种组成。一个标准数字相机拍摄的图像会有三通道 - 红、绿和蓝;你可以把它们看作是互相堆叠在一起的二维矩阵(每一个通道代表一个颜色),每个通道的像素值在 0 到 255 的范围内。 灰度图像,仅仅只有一个通道。在本篇文章中,我们仅考虑灰度图像,这样我们就只有一个二维的矩阵来表示图像。矩阵中各个像素的值在 0 到 255 的范围内——零表示黑色,255 表示白色。 2.卷积层2.1 卷积的数学定义卷积神经网络中很重要的就是卷积的概念,卷积本身是在泛函分析中的定义:卷积、旋积或摺积(Convolution)是通过两个函数f 和g 生成第三个函数的一种数学算子,表征函数f 与g经过翻转和平移的重叠部分的面积。 从定义可以看出,卷积是一种运算,因为从定义上得出的面积,基本可以看出可以通过积分来定义,这个积分就定义 了一个新的函数,如下,就不用数学公式来详细展开了,具体可以参考维基百科上的定义(如:连续定义(积分)和离散定义(求和))。 h(x)=f(x)*g(x)=(f*g)(x)2.2 卷积的物理意义从卷积的定义上可以看出,卷积主要是进行反转,平移,加权求和(积分);从定义上比较抽象,不易理解,从物理意义上进行解释便于理解,那么卷积计算的意义是什么呢? 平滑:卷积运算是一种线性运算,比如在图像中,将某个像素点用周围所有点进行加权求和值代替。 消除”噪声”:在1中的平滑和噪声消除相似,因为卷积本身就是进行加权求和,因此卷积后的值会过滤部分”噪声”。 空间显著性:卷积是对某一部分值进行操作,体现了空间的特性,能对空间中的特征进行增强。 空间变换:卷积在空间上有显著性,但是卷积本身是反转平移等操作,相当于进行了空间变换;比如某个物体,无论在空间的某个位置,卷积操作都可以将其特征抽取出来。 卷积在其他领域也有很多应用,比如频谱分析,信号处理等;也有很多其他物理意义,在这儿只是列举了部分具有代表性的物理意义。...
 2018-07-03   deep learning    tensorflow  deep learning  CNN  ReLU  convolution  pooling  BN 

深度学习-详解LSTM网络和TensorFlow实现

LSTM网络是RNN网络中的特殊网络,再RNN文章中已经提到,RNN在时间步过长时,学习不到依赖关系。主要是RNN会引起梯度消失和梯度爆炸这两个问题,因此为了解决问题,研究者们提出了很多方式,其中GRU和LSTM网络就是这样诞生的。LSTM网络在应用中也取得了非凡的成就,特别是在语音识别,语言建模,翻译等等方面。 1.长期依赖问题RNN的核心就是能将历史的信息连接到当前的场景下,即RNN对历史是有记忆功能的,能对一定时间步的信息进行记忆。但是time step过长的时候,就会出现问题,对过久(时间跨度太大的信息)信息没有记忆。从理论的角度RNN是有这样的功能,在应用中却不尽人意。为了解决这种长期依赖的问题,研究者提出了新的RNN模型,如GRU,LSTM等网络,来解决这种长期依赖的问题。 2.什么是LSTM网络LSTM,全称为长短期记忆网络(Long Short Term Memory networks),它也是一种特殊的RNN网络,但是可以学习到长期依赖的关系。那么LSTM是如何解决长期依赖的问题呢? 在RNN中我们也提到了,可以通过gate的方式来解决梯度消失和梯度爆炸的问题,而LSTM就是通过gate的方式来实现的。下面是LSTM的cell单元可视化结构。 下面是在整个时间序列上LSTM的整体结构,$X_t$表示不同时间点的输入序列,$h_t$为每个时间点的输出,从下面的结构图中可以看出LSTM网络中比RNN网络多了一个循环结构,从上面的结构中可以看出,LSTM Cell中多出了一个$C_t$的的变量,在LSTM中被称为记忆单元,记忆单元贯穿整个时间步,不会被输出,只会在循环过程中进行更新,并输出到下一时间步作为输入。$C_t$在每个cell中会进行简单的线性交互,上面承载了一些历史的输入信息。 ...
 2018-06-21   deep learning    tensorflow  deep learning  RNN  LSTM  gate 

深度学习-详解RNN网络及TensorFlow实现

1.RNN是什么RNN在维基上面有两种定义,但是一般默认的为时间递归神经网络,全称为(Recurrent Neural Network,简称为RNN)。RNN主要解决序列数据的处理,如文本,语音,视频等。典型应用在语言模型中,比如下面的示例: 我昨天上学迟到了,老师批评了____。 让机器在空的地方填词,这儿填写的词最有可能是”我”,但对于这样的模型通过什么来实现呢?RNN就是很好的选择,它很擅长处理序列数据。 传统的神经网络是层与层之间进行连接,但是每层之间的神经元是没有连接的(假设各个数据之间是相互独立的)。而RNN的结构就是当前层的数据和之前的输出也有关系,即每层之间的神经元不再是无连接,而是有连接的。基本结构可以通过下面表示: 上面的结构中非常清晰的表示了layer的结构,主要针对序列型的数据,各个神经元之间存在关联,每个时刻的状态会输入到后续的时刻中。 2.RNN结构RNN的大体结构如上图所示,也可以更加详细的表示,如下图中,输入,输出,状态项等。如下图中,存在一个循环结构,每个时间点的状态进行了下一时间点输入。 在上图中,输入单元(input units)为:$x_{t-1}, x_t, x_{t+1}$,输出单元(output units)为:$o_{t-1}, o_t, o_{t+1}$,隐藏单元(hidden units)为:$s_{t-1}, s_t, s_{t+1}$。 在某个时刻的隐层单元的输出:$s_t=f(Ws_{t-1}+Ux_t)$ ,其中$f$函数为激活函数,一般为sigmoid,tanh,relu等函数。在计算$s_0$时需要前面的状态,但是并不存在,因此一般设置为0向量。 某个时刻$t$的输出为:$o_t=softmax(Vs_t)=softmax(V(f(Ws_{t-1}+Ux_t)))$,其中$s_t$为时刻$t$的记忆单元。$s_t$包含了前面所有步的记忆,但是在实际使用过程中,$s_t$只会包含前面若干步的记忆,而不是所有步。 RNN中,每输入一步,每一层都共享参数$U,V,W$,RNN中主要在于隐藏层,在隐藏层能够捕捉到序列的关键信息。...
 2018-05-01   deep learning    tensorflow  deep learning  SGD  RNN