Universal Functions

Universal Functions

  • UFunc:在数组上执行逐元素运算函数

    • 支持广播、类型映射等
    • 可视为是函数的向量化包装
    • 基本ufunc在标量上执行操作,更泛化的ufunc也可以 在以子数组为基本元素进行操作
  • numpy中的ufuncnp.ufunc的实例

    • 许多内建的ufunc是通过C编译实现的
    • 可以通过np.frompyfunc工厂方法自定义ufunc实例
    • numpy中包含超过60种ufunc
      • 部分ufunc在相关运算标记调用时,会被自动调用

内部缓冲

  • Internal Buffers
    • 用于数据非对齐、数据交换、数据类型转换场合
    • .setbufsize(size):基于线程设置内部缓冲,缺省为 10,000元素

类型转换规则

  • ufunc内部维护列表,给出适用的输入类型(组合)、 相应的输出类型 (可通过.types属性查看)

  • ufunc内部列表中没有给定的输入类型组合时,则需要 进行safely类型转换 (可通过np.can_cast函数判断)

    • "S", "U", "V"类型不能支持ufunc运算
    • 标量-数组操作使用不同类型转换规则确保标量不会降低 数组精度,除非标量和数组属于同一类型体系

UFunc维度说明

  • core dimension:核心维度,ufunc执行操作所在的维度

    • 核心维度一般使用元组表示
      • 对一般ufunc:核心维度为空元组
      • 对广义ufunc:核心维度为非空元组、空元组
    • signature:签名,包含ufunc涉及的输出操作数和输出 操作数的核心维度字符串,如:(i,),(j,)->()
    • 签名中各输入操作数的对应核心维度大小必须相同,移除后 剩余的循环维度共同广播,加上输出操作数的核心维度得到 输出结果shape
  • loop dimension:循环维度,除核心维度之外的维度

UFunc原型

1
2
3
4
5
6
7
8
9
10
NDA = def numpy.<ufunc>(
x1 [,x2], /,
[out1, out2,], out, *,
where=True,
casting="same_kind",
order="K",
dtype=None,
subok=True,
[signature, extobj]
)
  • where=True/False/Array[bool]

    • 此参数不用于对子数组做操作的广义ufunc
  • keepdims=False/True

    • 对广义ufunc,只在输入操作数上有相同数量核心维度、 输出操作数没有核心维度(即返回标量)时使用
  • axes=tuple/int

    • 含义:广义ufunc执行操作、存储结果所在的轴序号
      • [tuple]:各元组为各输入操作数应被执行操作、 输出操作数存储结果的轴的序号
      • [int]:广义ufunc在1维向量上执行操作时,可以 直接使用整形
    • 若广义ufunc的输出操作数均为标量,可省略其对应元组
  • axis=int

    • 含义:广义ufunc执行操作所在的single轴序号
      • int:广义ufunc在相同的轴axis上执行操作, 等价于axes=[(axis,),(axis,),...]
  • signature=np.dtype/tuple[np.dtype]/str

    • 含义:指示ufunc的输入、输出的数据类型,
    • 对于底层计算1维loop,是通过比较输入的数据类型,找到 让所有输入都能安全转换的数据类型
      • 此参数允许绕过查找,直接指定loop
    • 可通过ufunc.types属性查看可用的signature列表
  • extobj=list

    • 含义:指定ufunc的缓冲大小、错误模式整数、错误处理 回调函数
      • list:长度为1、或2、或3的列表
    • 默认这些值会在对应线程字典中查找,此参数可以通过更 底层的控制
      • 可优化在小数组上大量ufunc的调用
  • 部分参数含义通用,参见README

UFunc属性

Attr Desc
ufunc.nin 输入数量
ufunc.nout 输出数量
ufunc.nargs 参数数量
ufunc.ntypes 类型数量
ufunc.types input->output列表
ufunc.identity 标志值
ufunc.signature 广义ufunc执行操作所在的核心元素的定义

UFunc方法

Method Desc
ufunc.reduce(a[,axis,dtype,out,...]) 通过沿轴应用ufunc缩减维度
ufunc.accumulate(array[,axis,dtype,out]) 累加所有元素的计算结果
ufunc.reduceat(a,indice[,axis,dtype,out]) 在single轴指定切片上执行reduce
ufunc.outer(A,B,**kwargs) 在分属A,B的元素对上应用ufunc
ufunc.at(a,indices[,b]) indices处在位无缓冲执行操作
  • 所有ufunc都有4个方法,但是这些方法只在标量ufunc、 包含2输入参数、1输出参数里有价值,否则导致ValueError

UFunc相关函数

Function Desc
apply_along_axis(func1d,axis,arr,*args,...) 沿给定轴应用函数
apply_over_axes(func,a,axes) 依次沿给定轴应用函数func(a,axis)
frompyfunc(func,nin,nout[,identity]) 创建ufunc,指定输入、输出数量
vertorize(pyfunc[,otypes,doc,excluded,cache,signature]) 创建ufunc,较frompyfunc提供更多特性
piecewise(x,condlist,funclist,*args,**kw) 按照condlist中索引,对应应用funclist中函数

NDArray开发

NDArray Interface/Protocol

  • 数组接口(规范):为重用数据缓冲区设计的规范
    • 接口描述内容
      • 获取ndarray内容的方式
      • 数组需为同质数组,即其中各元素数据类型相同
    • 接口包含C和Python两个部分
      • Python-API:对象应包含属性__array_interface__字典
      • C-API:结构体__array_struct__

https://www.numpy.org.cn/en/reference/arrays/interface.html#python-side

Python API

  • __array_interface__:由3个必须字段和5个可选字段构成
  • shape:各维度长度(使用时注意取值范围)

  • typestr:指明同质数组数据类型的字符串

    • 格式、含义基本同Array-Protocol,但有部分字符 含义不同
    • 但不同于自定义数据类型字符串,不指定结构化数据、 shape,非基本类型就是void,具体含义由descr 给出

    |代码|类型| |——-|——-| |'t'|bit| |'b'|boolean| |'B'|unsigned byte| |'i'|(signed) integer| |'u'|unsigned integer| |'f'|floating-point| |'c'|complex-floating point| |'m'|timedelta| |'M'|datetime| |'O'|(Python) objects| |'S'/'a'|zero-terminated bytes (not recommended)| |'U'|Unicode string| |'V'|raw data (void)|

  • descr:给出同质数组中各元素中内存布局的详细描述的 列表

    • 各元素为包含2、3个元素的元组
      • 名称:字符串、或(<fullname>,<basicname>) 形式的元组
      • 类型:描述基础类型字符串、或嵌套列表
      • shape:该结构的重复次数,若没有给出则表示无 重复
    • 一般此属性在typestr为取值为V[0-9]+时使用, 要求表示的内存字节数相同
    • 缺省为[(''), typestr]
  • data:给出数据位置的2元素元组或暴露有缓冲接口 的对象

    • 元组首个元素:表示存储数组内容的数据区域,指向 数据中首个元素(即offset被忽略)
    • 元素第二个元素:只读标记
    • 缺省为None,表示内存共享通过缓冲接口自身实现, 此时offset用于指示缓冲的开始
  • strides:存储各维度跃迁的strides的元组

    • 元组各元素为各维度跃迁字节数整形值,注意取值范围
    • 缺省为None,C-contiguous风格
  • mask:指示数据是否有效的暴露有缓冲接口的对象

    • 其shape需要同原始数据shape广播兼容
    • 缺省为None,表示所有数据均有效
  • offset:指示数组数据区域offset的整形值

    • 仅在数据为None或为buffer对象时使用
    • 缺省为0
  • version:指示接口版本

C API

  • __array_struct__:ctype的PyCObject,其中voidptr 指向PyArrayInterface

    • PyCObject内存空间动态分配
    • PyArrayInterface有相应的析构,访问其之后需要在其上 调用Py_DECREF
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    typedef struct{
    int two; // 值为2,sanity check
    int nd; // 维数
    char typekind; // 数组中数据类型
    int itemsize; // 数据类型size
    int flags; // 指示如何解释数据的标志
    // 5bits指示数据解释的5个标志位
    // `CONTIGUOUS` 0x01
    // `FROTRAN` 0x02
    // `ALIGNED` 0x100
    // `NOTSWAPPED` 0x200
    // `WRITABLE` 0X400
    // 1bit指示接口解释(是否包含有效`descr`字段)
    // `ARR_HAS_DESCR` 0x800
    Py_intptr_t *shape; // shape
    Py_intptr_t *strides; // strides
    void *data; // 指向数组中首个元素
    PyObject *descr; // NULL或数据描述(需设置`flags`中的`ARR_HAS_DESCR`,否则被忽略)
    } PyArrayInterface;

NDArray子类

子类相关钩子属性、方法

__array__方法

  • class.__array_ufunc__(ufunc, method, *inputs, **kwargs)

    • 功能:供自定义以覆盖numpy中ufunc行为
      • 返回操作结果,或NotImplemented (将此方法置None
    • 参数
      • ufunc:被调用的ufunc对象
      • method:字符串,指示调用的ufunc对象的方法
      • inputsufunc顺序参数元组
      • kwargsufunc关键字参数字典
    • Ufunc、与__array_ufunc__关系参见ufunc部分
  • class.__array_function__(func,types,args,kwargs)

    • 参数
      • func:任意callable,以func(*args, **kwargs) 形式调用
      • types:来自实现`
      • argskwargs:原始调用的参数
  • class.__array__finalize(obj)

    • 功能:构造之后更改self的属性
      • 在为obj类型数组分配空间时调用
    • 参数
      • objndarray子类
  • class.__array_prepare__(array,context=None)

    • 功能:在ufunc计算前,将ouput数组转换为子类实例、 更新元数据
      • 调用任何ufunc前,在最高优先级的input数组,或指定 的output数组上调用,返回结果传递给ufunc
      • 默认实现:保持原样
  • class.__array_wrap__(array,context=None)

    • 功能:在将结果返回给用户前,将output数组转换为子类 实例、更新元信息
      • ufunc计算结果返回给用户前,在最高优先级的output 数组、或指定output对象上调用
      • 默认实现:将数组转换为新
  • class.__array__([dtype])

    • 功能:若output对象有该方法,ufunc结果将被写入其 返回值中
  • 若ufunc中所有__array_ufunc__返回NotImplemented,那么 raise TypeError

__array__属性

  • class.__array_priority__
    • 功能:决定返回对象的数据类型(有多种可能性时)
      • 默认值:0.0

Matrix

np.matrix

Matrix对象:继承自ndarray,具有ndarray的属性、方法

  • Matrix对象的特殊行为
    • 维数始终为2
      • .ravel()仍然二维
      • item selection返回二维对象
    • 数学操作
      • 覆盖乘法为矩阵乘法
      • 覆盖幂次为矩阵幂次
    • 属性
      • 默认__array_priority__10.0
  • Matrix类被设计用于与scipy.sparse交互,建议不使用
  • np.matnp.matrix别名

Matrix对象property属性

Property Desc
matrix.T 转置
matrix.H 复数共轭
matrix.I 逆矩阵
matrix.A 返回ndarray

Matrix创建

Routine Desc
np.mat(data[,dtype]) 创建矩阵
np.matrix(data[,dtype,copy]) 不建议使用
np.asmatrix(data[,dtype]) 将数据转换为矩阵
np.bmat(obj[,ldict,gdict]) 从字符串、嵌套序列、数组中构建
  • mp.bmat:可使用Matlab样式字符串表示法创建Matrix
    • 空格分割列
    • ;分割行

np.matlib

  • numpy.matlib模块中包含numpy命名空间下所有函数
    • 返回matrix而不是ndarray
    • matrix被限制为小于2维,会改变形状的函数可能无法 得到预期结果
  • np.matlib是为了方便矩阵运算的模块

np.char

np.chararray

  • np.chararray类:string_unicode_数据类型的增强型 数组,继承自ndarray
    • 继承由Numarray引入的特性:项检索和比较操作中,数组 元素末尾空格被忽略
    • 定义有基于元素的+*%的操作
    • 具有所有标准stringunicode方法,可以逐元素执行
Routine Function Version
char.array(obj[,itemsize,...])
char.asarray(obj[,itemsize,...]) 转换输入为chararray,必要时复制数据
chararray(shape[,itemsize,unicode,...]) 不应直接使用此构造函数
  • np.chararray类是为了后向兼容Numarray,建议使用 object_string_unicode_类型的数组替代,并利用 numpy.char模块的自由函数用于字符串快速向量化操作

NDArray Char Routine

  • np.char/np.core.defchararray模块为np.string_np.unicode_类型的数组提供向量化的字符串操作
    • 基于标准库中stringunicode的方法

字符串操作

Routine Function Version
char.add(x1,x2)
char.multiply(a,i)
char.mod(a,values) %格式化(str.__mod__%调用方法)
char.capialize(a) 首字符大写
char.title(a) 单词首字符大写
char.center(a,width[,fillchar]) a居中、fillchar填充字符串
char.ljust(a,width(,fillchar)) a靠左
char.rjust(a,width(,fillchar)) a靠左
char.zfill(a,width) 0填充左侧
char.char.decode(a[,encoding,errors])
char.char.encode(a[,encoding,errors])
char.char.expandtabs(a[,tabsize]) 替换tab为空格
char.join(sep, seq)
char.lower(a)
char.upper(a)
char.swapcase(a)
char.strip(a[,chars])
char.lstrip(a[,chars])
char.rstrip(a[,chars])
char.partition(a,sep) 从左至右切分一次,返回三元组
char.rpartition(a,sep) 从右至左切分一次
char.split(a[,sep,maxsplit]) 从左至右切分maxsplit次,返回列表
char.rsplit(a[,sep,maxsplit])
char.splitlines(a[,keepends]) 切分行,即\n为切分点
char.replace(a,old,new[,count])

Camparison

Function Desc
equal(x1,x2)
greater(x1,x2)
less(x1,x2)
not_equal(x1,x2)
greater_equal(x1,x2)
less_equal(x1,x2)
compare_chararrays(a,b,com_op,rstrip) com_op指定比较方法

字符串信息

Function Desc
count(a,sub[,start,end]) 统计不重叠sub出现次数
startwith(a,prefix[,start,end])
endswith(a,suffix[,start,end])
find(a,sub[,start,end]) 返回首个sub位置,不存在返回-1
rfind(a,sub[,start,end]) 从右至左find
index(a,sub[,start,end]) find,不存在ValueError
rindex(a,sub[,start,end]) 从右至左index
isalpha(a)
iaalnum(a)
isdecimal(a)
isdigit(a)
islower(a)
isnumeric(a)
isspace(a)
istitle(a) 是否各单词首字符大写
isupper(a)
str_len(a)

np.rec

  • np.rec/np.core.records

np.recarray

  • np.recarray类:允许将结构化数组的字段作为属性访问
Routine Function Version
np.recarray 创建允许属性访问字段的ndarray
np.record 允许使用属性查找字段的数据类型标量

Record Arrays

Routine Function Version
core.records.array(obj[,dtype,shape,...]) 从多类型对象中创建
core.records.fromarrays(arrayList[,dtype,...]) 从数组列表中创建
core.records.fromrecords(recList[,dtype]) 从文本格式的records列表创建
core.records.fromstring(datastring[,dtype,...]) 从二进制数据字符串中创建只读
core.records.fromfile(fd[,dtype,shape,...]) 从二进制文件中创建

np.ma

ma.MaskedArray

  • ma.MaskedArray:掩码数组,是np.ma核心,ndarray子类

    • ma.MaskedArray由标准np.ndarray和掩码组成
  • 掩码数组.mask

    • 掩码可以被设置为hardmasksoftmask,由只读属性 hardmask指定
      • hardmask:无法修改被遮蔽值
      • softmask:可修改被遮蔽值,并恢复被遮蔽状态
    • .mask可以被设置
      • 为bool数组,指示各位置元素是否被遮蔽
      • ma.maskded/ma.unmask/True/False,设置掩码数组 整体是被遮蔽

属性

Attr Desc
.hardmask 硬掩码标志
.data 值数组
.mask 掩码数组、ma.unmaskma.masked
.recordmask 项目中命名字段全遮蔽则遮蔽

创建掩码数组

Routine Function Version Method Version
ma.MaskedArray(data[,mask,dtype,...])
ma.masked_array(data[,mask,dtype,...]) MaskedArray别名
ma.array(data[,dtype,copy,...]) 构造函数
ma.frombuffer(buffer[,dtype,count,offset])
ma.fromfunction(function,shape,dtype)
ma.fromflex(fxarray) 从有_data_mask字段的结构化fxarray中创建
copy(a[,order])
Ones and Zeros
Routine Function Version
ma.empty(shape[,dtype,order]) 无初始化
ma.empty_like(prototype[,dtype,order,subok,...]) shape、类型同prototype
ma.ones(shape[,dtype,order])
ma.zeros(shape[,dtype,order])
ma.masked_all(shape[,dtype]) 所有元素被屏蔽
ma.masked_all_like(shape[,dtype])

MaskedArray Routine

  • np.ma模块下的函数、ma.MaskedArray方法和ndarray 类似,但行为可能不同
    • np命名空间下部分函数(hstack等)应用在 MaskedArray
      • 操作时忽略mask(即会操作被遮罩元素)
      • 返回结果中mask被置为False
  • 这里仅记录ma模块中额外、或需额外说明部分

数组检查

Routine Function Version Method Version
ma.all(a[,axis,out,keepdims]) 全遮蔽时返回ma.masked
ma.any(a[,axis,out,keepdims]) 存在遮蔽时返回ma.masked
ma.count(arr,[axis,keepdims]) 沿给定轴统计未被遮罩元素数量
ma.count_masked(arr,[axis]) 沿给定轴统计被遮罩元素数量
ma.nonzero(a) 非0、未屏蔽元素索引
ma.is_mask(m) 是否为标准掩码数组
ma.is_masked(x) 是否包含遮蔽元素

获取、创建、修改掩码

Routine Function Version Method Version
ma.getmask(a) 返回掩码、或ma.nomaskma.masked .mask属性
ma.getmaskarray(arr) 返回掩码、或完整False数组
ma.make_mask(m[,copy,shrink,dtype]) 从数组创建掩码
ma.make_mask_none(newshape[,dtype]) 创建给定形状掩码
ma.make_mask_descr(ndtype) 为给定类型的创建掩码类型
ma.mask_rowcols(a[,axis]) 遮蔽包含遮蔽元素的axis方向分量
ma.mask_rows(a[,axis]) 缺省为0mask_rowcols()
ma.mask_cols(a[,axis]) 缺省为1mask_rowcols()
ma.mask_mask_or(m1,m2[,copy,shrink]) 掩码或
ma.harden_mask(a)
ma.soften_mask(a)
.shrink_mask() 尽可能缩小掩码
.share_mask() 复制掩码,并设置sharedmask=False

获取、创建索引

  • 索引非结构化掩码数组

    • mask为False:返回数组标量
    • mask为True:返回ma.masked
  • 索引结构化掩码数组

    • 所有字段mask均为False:返回np.void对象
    • 存在字段mask为True:返回零维掩码数组
  • 切片

    • .data属性:原始数据视图
    • .mask属性:ma.nomask或者原始mask视图
Routine Function Version Method Version
ma.nonzero(a) 未屏蔽、非0元素索引
ma.mr_[] 沿第1轴concate切片、数组、标量,类np.r_[]
ma.flatnotmasked_contiguous(a) 展平后未遮蔽切片
ma.flatnotmasked_edges(a) 展平后首个、末个未遮蔽位置
ma.notmasked_contiguous(a[,axis]) 沿给定轴,未遮蔽切片
ma.notmasked_edges(a[,axis]) 沿给定轴,首个、末个未遮蔽位置
ma.clump_masked(a) 展平后遮蔽切片
ma.clump_unmasked(a) 展位后未遮蔽切片
  • ma.mr_[]类似np.r_[],但np.r_[]返回结果掩码被置为 False,而ma.mr_[]同时也操作掩码

获取、修改值

  • 仅访问有效数据

    • 对掩码mask取反作为索引~X.mask
    • 使用.compressed方法得到一维ndarray
    1
    2
    print(X[~X.mask])
    print(X.compressed())
  • 访问数据

    • 通过.data属性:可能是ndarray或其子类的视图
      • 等同于直接在掩码数组上创建ndarray或其子类视图
    • __array__方法:ndarray
    • 使用ma.getdata函数
Routine Function Version Method Version
ma.getdata(a[,subok]) 返回掩码数组数据 .data属性
ma.fix_valid(a[,mask,copy,fill_value]) 替换a中无效值,并遮盖
ma.masked_equal(x,value[,copy])
ma.masked_greater(x,value[,copy])
ma.masked_greater_equal(x,value[,copy])
ma.masked_inside(x,v1,v2[,copy])
ma.masked_outside(x,v1,v2[,copy])
ma.masked_invalid(x[,copy])
ma.masked_less(x,value[,copy])
ma.masked_less_equal(x,value[,copy])
ma.masked_not_equal(x,value[,copy])
ma.masked_values(x,value[,rtol,atol,...])
ma.masked_object(x,value[,copy,shrink]) masked_values,适合值类型为object
ma.masked_where(condition,a[,copy]) condition遮蔽指定值

其他属性、方法

Routine Function Version Method Version
ma.common_fill_value(a,b) a,b填充值相同则返回,否则返回None
ma.default_fill_value(obj) 默认填充值
ma.maximum_fill_value(obj) 对象类型决定的最大值
ma.minimum_fill_value(obj)
ma.sef_fill_value(a,fill_value)
.get_fill_value()/.fill_value
ma.allequal(a,b[,fill_value]) a,b元素均相等,则使用fill_value填充

np.ma运算

  • 掩码数组支持代数、比较运算

    • 被遮蔽元素不参与运算,元素在运算前后保持不变
    • 掩码数组支持标准的ufunc,返回掩码数组
      • 运算中任意元素被遮蔽,则结果中相应元素被遮蔽
      • ufunc返回可选的上下文输出,则上下文会被处理, 且无定义结果被遮蔽
  • np.ma模块中对大部分ufunc有特别实现

    • 对于定义域有限制的一元、二元运算,无定义的结果会 自动mask
    1
    ma.log([-1, 0, 1, 2])
Routine Function Version Method Version
ma.anom(a[,axis,dtype]) 沿给定轴计算与算数均值的偏差

np.memmap

  • np.memmap:内存映射文件数组,使用内存映射文件作为数组 数据缓冲区

    • 对大文件,使用内存映射可以节省大量资源
  • 方法

    |Method|Desc| |——-|——-| |np.memmap(filename[,dtype,mode,shape])|创建存储在磁盘文件的内存映射数组| |np.flush()|flush内存数据至磁盘|

标准容器类

  • np.lib.user_array.container

    • 为向后兼容、作为标准容器类而引入
    • 其中self.array属性是ndarray
    • ndarray本身更方便多继承
  • 类、方法、函数

    |Method|Desc| |——-|——-| |np.lib.user_array.container(data[,...])|简化多继承的标准容器类|

NDArray标量

NDArray标量类型

  • numpy中定义了24种新python类型(NDArray标量类型)

    • 类型描述符主要基于CPython中C语言可用的类型
  • 标量具有和ndarray相同的属性和方法

    • 数组标量不可变,故属性不可设置

numpy_dtype_hierarchy

内置标量类型

Routine Desc
iinfo(int_type) 整数类型的取值范围等信息
finfo(float_type) 浮点类型的取值范围等信息

Python关联

NumPy类型 Python类型 64位NumPy定长类型 Desc
int_ 继承自int(Python2) int64
float_ 继承自float float64
complex_ 继承自complex complex128
bytes_ 继承自bytes S#"/"a#" Python字节串
unicode_ 继承自str "U#" Python字符串
void "V#" Python缓冲类型
object_ 继承自object(Python3) "O" Python对象引用
  • np.bool_类似Python中bool类型,但不继承它

    • Python中bool类型不允许被继承
    • np.bool_大小和bool类型大小不同
  • np.int_不继承自int,因为后者宽度不再固定

    • NumPy中数组没有真正np.int类型,因为宽度不再固定, 各产品
  • bytes_unicode_void是可灵活配置宽度的类型

    • 在指定长度后不能更改,赋长于指定长度的值会被截断
    • unicode_:强调内容为字符串
    • bytes_:强调内容为字节串
    • void:类型强调内容为二进制内容,但不是字节串
  • object_存储的是python对象的引用而不对象本身

    • 其中引用不必是相同的python类型
    • 兜底类型
  • Python基本类型等在NumPy命名空间下都有同名别名,如: np.unicode == np.str == str
  • NumPy数组中数据类型无法被真正设置为int类型,为保证数组 中元素宽度一致性,必然无法被设置为非定长类型

C类型关联

  • NumPy支持的原始类型和C中原始类型紧密相关
NumPy类型 C类型 64位定长别名 Desc 单字符代码 定长字符串代码
bool_ bool bool8 存储为字节的bool值 "?"
byte signed char int8 "b" "i1"
short short int16 "h" "i2"
intc int int32 "i" "i4"
int_ long int64 "l" "i8"
longlong long long "q"
ubyte unsigned char uint8 "B" "u1"
ushort unsigned short uint16 "H" "u2"
uintc unsigned int uint32 "I" "u4"
uint usigned long uint64 "L" "u8"
ulonglong unsigned long long "Q"
half float16 半精度浮点:1+5+10 "e" "f2"
single float float32 单精度浮点,通常为:1+8+23 "f4"
double double float64 双精度浮点,通常为:1+11+52 "d" "f8"
longdouble/longfloat long double float128 平台定义的扩展精度浮点 "g" "f16"
csingle float complex complex64 两个单精度浮点 "F" "c8"
cdouble/cfloat double complex complex128 两个双精度浮点 "D" "c16"
clongdouble/clongfloat long duoble complex complex256 两个扩展精度浮点 "G" "c32"
  • float complexdouble complex类型定义在complex.h
  • C中的定长类型别名定义在stdint.h

其他类型

Python类型 Desc 单字符代码 定长字符串代码
timedelta64 时间增量 "m" "m8"
datetime64 日期时间 "M" "M8"

属性、索引、方法

  • 数组标量属性基本同ndarray

  • 数组标量类似0维数组一样支持索引

    • X[()]返回副本
    • X[...]返回0维数组
    • X[<field-name>]返回对应字段的数组标量
  • 数组标量与ndarray有完全相同的方法

    • 默认行为是在内部将标量转换维等效0维数组,并调用相应 数组方法

定义数组标量类型

  • 从内置类型组合结构化类型
  • 子类化ndarray
    • 部分内部行为会由数组类型替代
  • 完全自定义数据类型,在numpy中注册
    • 只能使用numpy C-API在C中定义

数据类型相关函数

数据类型信息

Function Desc
finfo(dtype) 机器对浮点类型限制
iinfo(type) 机器对整型限制
MachAr([float_conv,int_conv]) 诊断机器参数
typename(char) 对给定数据类型字符代码的说明

数据类型测试

Function Desc
can_cast(from_,to[,casting]) 是否可以类型转换
issctype(rep) rep(不能为可转换字符串)是否表示标量数据类型
issubdtype(arg1,arg2) arg1在数据类型层次中较低(即dtypeissubclass
issubsctype(arg1,arg2) issubdtype,但支持包含dtype属性对象作为参数
issubclass_(arg1,arg2) 同内置issubclass,但参数非类时仅返回False,而不是raise TypeError
  • np.int64np.int32在层次体系中不同、且层级一致,所以 会出现issubdtype(np.int64, int) -> True,其他情况为 False

  • 通过np.can_cast函数确定safely类型转换

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def print_casting(ntypes):
    print("X")
    for char in ntypes:
    print(char, end=" ")
    print("")
    for row in ntypes:
    print(row, end=" ")
    for col in ntypes:
    print(int(np.can_cast(row, col)), end=" ")
    print("")
    print_casting(np.typecodes["All"])

数据类型确定

Function Params ReturnType ReturnDesc
min_scalar_type(a) 标量值 dtype实例 满足要求最小类型
promote_types(type1,type2) dtype等 dtype实例 可安全转换的最小类型
result_type(*array_and_dtypes) dtype等、标量值、数组 dtype实例 应用promotion rules得到类型
find_common_type(array_types,scalar_types) dtype等列表 dtype实例 综合考虑标量类型、数组类型
common_type(*arrays) 数值型数组(有dtype属性) 预定义类型 满足要求类型中、最高精度类型
maximum_sctype(t) dtype等、标量值、数组 预定义类型 满足要求类型中、最高精度类型
obj2sctype(rep[,default]) dtype等、标量值、数组 预定义类型 对象类型
sctype2char(sctype) dtype等、标量值、数组 类型字符代码 满足要求的最小类型
mintypecode(typechars[,typeset,default]) dtype等、标量值、数组 类型字符代码 typeset中选择
  • 除非标量和数组为不同体系内数据类型,否则标量不能up_cast 数组数据类型

数据类型类np.dtype

1
class dtype(obj[,align,copy])
  • numpy.dtype类描述如何解释数组项对应内存块中字节

    • 数据大小
    • 数据内存顺序:little-endianbig-endian
    • 数据类型
      • 结构化数据
        • 各字段名称
        • 各字段数据类型
        • 字段占用的内存数据块
      • 子数组
        • 形状
        • 数据类型
  • numpy.dtype实例作为参数的场合,大部分场景可用等价、 可转换为dtype实例的其他值代替

    • python、numpy中预定义的标量类型、泛型类型
    • 创建dtype实例类型的字符串、字典、列表
    • 包含dtype属性的类、实例

数据类型元素

类型类

  • NumPy内置类型

    • 24中内置数组标量类型
    • 泛型类型

      |Generic类型|转换后类型| |——-|——-| |number,inexact,floating|float_| |complexfloating|complex_| |integer,signedinteger|int_| |unsignedinteger|uint| |character|string| |generic,flexible|void|

  • python内置类型,等效于相应数组标量

    • 转换规则同NumPy内置数组标量类型
    • None:缺省值,转换为float_

      |Python内置类型|转换后类型| |——-|——-| |int|int_| |bool|bool_| |float|float_| |complex|complex_| |bytes|bytes_| |str|unicode_| |unicode|unicode_| |buffer|void| |Others|object_|

  • 带有.dtype属性的类型:直接访问、使用该属性

    • 该属性需返回可转换为dtype对象的内容

可转换类型的字符串

  • numpy.sctypeDict.keys()中字符串

  • Array-protocal类型字符串,详细参见NumPy数组标量类型

    • 首个字符指定数据类型
    • 支持指定字节数的字符可在之后指定项目占用字节数
      • 定长类型只能指定满足平台要求的字节数
      • 非定长类型可以指定任意字节数

    |代码|类型| |——-|——-| |'?'|boolean| |'b'|(signed) byte,等价于'i1'| |'B'|unsigned byte,等价于'u1'| |'i'|(signed) integer| |'u'|unsigned integer| |'f'|floating-point| |'c'|complex-floating point| |'m'|timedelta| |'M'|datetime| |'O'|(Python) objects| |'S'/'a'|zero-terminated bytes (not recommended)| |'U'|Unicode string| |'V'|raw data (void)|

结构化数据类型

Function Desc
format_parser(formats,names,titles[,aligned,byteorder]) 创建数据类型
dtype(obj[,align,copy])
  • 结构化数据类型

    • 包含一个或多个数据类型字段,每个字段有可用于访问的 名称
    • 父数据类型应有足够大小包含所有字段
    • 父数据类型几乎总是基于void类型
  • 仅包含不具名、单个基本类型时,数组结构会穿透

    • 字段不会被隐式分配名称
    • 子数组shape会被添加至数组shape

参数格式

  • 可转换数据类型的字符串指定类型、shape

    • 依次包含四个部分
      • 字段shape
      • 字节序描述符:<>|
      • 基本类型描述符
      • 数据类型占用字节数
        • 对非变长数据类型,需按特定类型设置
        • 对变长数据类型,指字段包含的数量
    • 逗号作为分隔符,分隔多个字段
    • 各字段名称只能为默认字段名称
    • 对变长类型,仅设置shape时,会将其视为bytes长度
    1
    dt = np.dtype("i4, (2,3)f8, f4")
  • 元组指定字段类型、shape

    • 元组中各元素指定各字段名、数据类型、shape: (<field_name>, <dtype>, <shape>)
      • 若名称为''空字符串,则分配标准字段名称
    • 可在列表中多个元组指定多个字段 [(<field_name>, <dtype>, <shape>),...]
    • 数据类型dtype可以嵌套其他数据类型
      • 可转换类型字符串
      • 元组/列表
    1
    2
    3
    dt = np.dtype(("U10", (2,2)))
    dt = np.dtype(("i4, (2,3)f8, f4", (2,3))
    dt = np.dtype([("big", ">i4"), ("little", "<i4")])
  • 字典元素为名称、类型、shape列表

    • 类似format_parser函数,字典各键值对分别指定名称 列表、类型列表等: {"names":...,"formats":...,"offsets":...,"titles":...,"itemsize":...}
      • "name""formats"为必须
      • "itemsize"指定总大小,必须足够大
    • 分别指定各字段:"field_1":..., "field_2":...
      • 不鼓励,容易与上一种方法冲突
    1
    2
    3
    4
    dt = np.dtype({
    "names": ['r', 'g', 'b', 'a'],
    "formats": ["u1", "u1", "u1", "u1"]
    })
  • 解释基数据类型为结构化数据类型: (<base_dtype>, <new_dtype>)

    • 此方式使得union成为可能
    1
    dt = np.dtype(("i4", [("r", "I1"), ("g", "I1"), ("b", "I1"), ("a", "I1")]))

属性

  • 描述数据类型

    |属性|描述| |——-|——-| |.type|用于实例化此数据类型的数组标量类型| |.kind|内置类型字符码| |.char|内置类型字符码| |.num|内置类型唯一编号| |.str|类型标识字符串|

  • 数据大小

    |属性|描述| |——-|——-| |.name|数据类型位宽名称| |.itemsize|元素大小|

  • 字节顺序

    |属性|描述| |——-|——-| |.byteorder|指示字节顺序|

  • 字段描述

    |属性|描述| |——-|——-| |.fields|命名字段字典| |.names|字典名称列表|

  • 数组类型(非结构化)描述

    |属性|描述| |——-|——-| |.subtype|(item_dtype,shape)| |.shape||

  • 附加信息

    |属性|描述| |——-|——-| |.hasobject|是否包含任何引用计数对象| |.flags|数据类型解释标志| |.isbuiltin|与内置数据类型相关| |.isnative|字节顺序是否为平台原生| |.descr|__array_interface__数据类型说明| |.alignment|数据类型需要对齐的字节(编译器决定)| |.base|基本元素的dtype|

方法

  • 更改字节顺序

    |方法|描述| |——-|——-| |.newbyteorder([new_order])|创建不同字节顺序数据类型|

  • Pickle协议实现

    |方法|描述| |——-|——-| |.reduce()|pickle化| |.setstate()||

Datetime

  • Numpy种时间相关数据类型
    • 支持大量时间单位
    • 基于POSIX时间存储日期时间
    • 使用64位整形存储值,也由此决定了时间跨度

np.datetime64

  • np.datetime64表示单个时刻
    • 若两个日期时间具有不同单位,可能仍然代表相同时刻
    • 从较大单位转换为较小单位是安全的投射

创建

  • 创建规则

    • 内部存储单元自动从字符串形式中选择单位
    • 接受"NAT"字符串,表示“非时间”值
    • 可以强制使用特定单位
  • 基本方法:ISO 8601格式的字符串

    1
    2
    np.datetime64("2020-05-23T14:23")
    np.datetime64("2020-05-23T14:23", "D")
  • 从字符串创建日期时间数组

    1
    2
    3
    np.array(["2020-01-23", "2020-04-23"], dtype="datetime64")
    np.array(["2020-01-23", "2020-04-23"], dtype="datetime64[D]")
    np.arange("2020-01-01", "2020-05-03", dtype="datetime64[D]")
  • np.datetime64为向后兼容,仍然支持解析时区

np.timedelta64

  • np.timedelta64:时间增量
  • np.timedelta64是对np.datetime64的补充,弥补Numpy对 物理量的支持

创建

  • 创建规则

    • 接受"NAT"字符串,表示“非时间”值数字
    • 可以强制使用特定单位
  • 直接从数字创建

    1
    np.timedelta64(100, "D")
  • 从已有np.timedelta64创建,指定单位

    • 注意,不能将月份及以上转换为日,因为不同时点进制不同
    1
    np.timedelta(a, "M")

运算

  • np.datetime64可以和np.timedelta64联合使用

    1
    2
    np.datetime64("2020-05-14") - np.datetime64("2020-01-12")
    np.datetime64("2020-05-14") + np.timedelta64(2, "D")

相关方法

Function Desc
np.busdaycalendar(weekmask,holidays) 返回存储有效工作日对象
np.busday_offset(date,offset[,roll,weekmask,holidays,busdaycal,out]) 工作日offset
np.is_busday(date[,weekmask,holidays,busdaycal,out]) 判断是否是工作日
np.busday_count(begindates,enddates[,weekmask,holidays,busdaycal,out]) 指定天数
np.datetime_as_string(arr[,unit,timezone,...]) 转换为字符串数组
np.datetime_date(dtype,/) 获取日期、时间类型步长信息
  • np.busday_offset
    • roll缺省为"raise",要求date本身为工作日

NDArray

NDArray

1
class ndarray(shape[,dtype,buffer,offset])
  • ndarray:具有相同类型、大小(固定大小)项目的多维容器

    • ndarray由计算中内存连续的一维段组成,并与将N个整数 映射到块中项的位置的索引方案相结合
    • 可以共享相同数据段,即可以是其他数据区的视图
      • 另一个ndarray
      • 实现buffer的对象
  • 属性

    • shape:指定尺寸、项目数量
    • dtypedata-type object):指定项目类型
    • strides:存储各维度步幅,用于计算连续数据段中偏移

https://www.numpy.org.cn/reference/arrays/ndarray.html/https://www.numpy.org.cn/reference/arrays/ndarray.html

Broadcast 广播规则

Broadcasting:4条广播规则用于处理不同shape的数组

  • 非维数最大者在shape前用1补足
  • 输出的shape中各维度是各输入对应维度最大值
  • 各输入的维度同输出对应维度相同、或为1
  • 输入中维度为1者,对应的(首个)数据被用于沿该轴的 所有计算 (即对应的stride0ufunc不step along该维度)
1
2
3
4
5
shape(3, 2, 2, 1) + shape(1, 3)
-> shape(3, 2, 2, 1) + shape(1, 1, 1, 3)
-> shape(3, 2, 2, 3) + shape(1, 1, 2, 3)
-> shape(3, 2, 2, 3) + shape(1, 2, 2, 3)
-> shape(3, 2, 2, 3) + shape(3, 2, 2, 3)

数组属性

内存布局

属性 描述
ndarray.flags 有关数组内存布局的信息
ndarray.shape 数组维度(元组)
ndarray.strides 遍历数组时每个维度中的字节数量(元组)
ndarray.ndim 数组维数
ndarray.data Python缓冲区对象指向数组的数据的开头
ndarray.size 数组中的元素数
ndarray.itemsize 数组元素的长度,以字节为单位
ndarray.nbytes 数组元素消耗的总字节数
ndarray.base 如果内存来自其他对象,则为基础对象

数据类型

属性 描述
ndarray.dtype 元素数据类型

其他属性

属性 描述
ndarray.T 转置
ndarray.real 实数部分
ndarray.imag 虚数部分
ndarray.flat 数组的一维迭代器

数组接口

属性 描述
__array_interface__ 数组接口python端
__array_struct__ 数组接口C语言端

ctypes外部函数接口

属性 描述
ndarray.ctypes 简化数组和ctypes模块交互的对象

np.nditer

  • ndarray对象的默认迭代器是序列类型的默认迭代器

    • 即以对象本身作为迭代器时,默认行为类似

      1
      2
      for i in range(X.shape[0]):
      pass
Routine Function Version Method Version
nditer(op[,flags,op_flags,...]) 高性能迭代器
nested_iters(op,axes[,flags,op_flags,...]) 在多组轴上嵌套创建nditer迭代器
ndenumerate(arr) (idx,val)迭代器
lib.Arrayterator(var[,buf_size]) 适合大数组的缓冲迭代
flat 返回np.flatiter迭代器
ndindex(*shape) 迭代shape对应数组的索引

np.nditer

1
2
3
4
5
6
7
8
9
10
11
class np.nditer(
op,
flags=None,
op_flags=None,
op_dtypes=None,
order='K'/'C'/'F'/'A',
casting='safe',
op_axes=None,
itershape=None,
buffersize=0
)
  • 迭代方式

    • 通过标准python接口迭代数组中各数组标量元素
    • 显式使用迭代器本身,访问其属性、方法
      • np.nditer[0]访问当前迭代的结果
      • np.iternext()获取下个迭代对象
  • 包含特殊属性、方法获取额外信息(可能需设置迭代标志)

    • 跟踪索引:获取索引np.nditer.indexnp.nditer.multi_index
    • 手动迭代np.nditer.iternext()得到下个 np.nditer对象
    • 获取操作数np.nditer.operands:迭代器关闭之后 将无法访问,需要在关闭前获得引用

https://www.numpy.org.cn/reference/arrays/nditer.html

参数

  • flags:迭代器标志

    • buffered:允许缓冲
      • 增大迭代器提供给循环内部的数据块
      • 减少开销、提升性能
    • c_index:track C顺序索引
    • f_index:track C顺序索引
    • multi_index:track 多维索引
    • common_dtype:将所有操作数转换为公共类型
      • 需设置copyingbuffered
    • copy_if_overlap:迭代器决定是否读操作数覆盖写 操作数,还是使用临时副本避免覆盖
    • delay_bufalloc:延迟缓冲区设置直至reset()函数 调用
      • 允许allocate操作数在其值被复制到缓冲区前初始化
    • external_loop:迭代一维数组而不是零维数组标量
      • 利于矢量化操作
      • 返回的循环块与迭代顺序相关
    • grow_inner:允许迭代数组大小大于缓冲区大小
      • bufferedexternal_loop均设置情况下
    • ranged
    • refs_ok:允许迭代引用类型,如object数组
    • reduce_ok:允许迭代广播后的readwrite操作数 (也即reduction操作数)
    • zerosize_ok:允许迭代大小为0
  • op_flags

    • readonly:操作数只能被读取
    • readwrite:操作数能被读写
    • writeonly:操作只能被写入
    • no_broadcast:禁止操作数被广播
    • contig:强制操作数数据连续
    • aligned:强制操作数数据对齐
    • nbo:强值操作数数据按原生字节序
    • copy:允许临时只读拷贝
    • updateifcopy:允许临时读写拷贝
    • allocate:允许数组分配若op中包含None
      • 迭代器为None分配空间,不会为非空操作数分配 空间,即使是广播后赋值空间不足
      • 操作数中opNone对应op_flags缺省为 ["allocate", "writeonly"]
    • no_subtype:阻止allocate操作数使用子类型
    • arraymask:表明对应操作数为mask数组
      • 用于从设置有writemasked标志的操作数中选择写回 部分
    • writemasked:只有arraymask操作数选择的元素被写回
    • overlap_assume_elementwise:标记操作数只能按照迭代 顺序获取
      • 允许在copy_if_overlap设置的场合,更保守的拷贝
  • op_dtypes:操作数需求的数据类型

    • 在循环内对单个值进行数据类型转换效率低
    • 迭代器以缓冲、复制整体进行类型转换提高效率
    • 需要同时设置"copy""buffered",否则因无法复制、 缓冲报错(类型不同时) (类型转换不修改原数组值,需要额外空间存储转换后值)
  • order:迭代顺序

    • C/F:C风格、Fortran风格
    • A:若所有数组均为Fortran风格则为Fortran风格,否则 为C风格
    • K:尽量贴近内存布局
    • allocate操作数的内存布局会兼容此参数设置
  • casting:指明在拷贝、缓冲时允许的数据类型转换规则 (包括读取、写回数组时可能的类型转换)

    • no:不允许任何类型转换
    • equiv:仅允许字节顺序改变
    • safe:仅允许可保证数据精度的类型转换
    • same_kind:只能允许safe或同类别类型转换
    • unsafe:允许所有类型转换
  • op_axes:设置迭代器维度到操作数维度的映射

    • 需为每个操作数设置维度映射
  • itershape:设置迭代器的shape

  • buffersize:设置缓冲区大小

    • buffered设置的情况下
    • 0表示默认大小

使用说明

  • 控制迭代顺序

    • 设置order参数
    • 缺省按照内存布局迭代
      • 提高效率
      • 适合不关心迭代顺序场合
    1
    2
    3
    4
    5
    6
    # 二者迭代顺序完全相同
    np.nditer(X, order="K")
    np.nditer(X.T)
    # 指定按C或Fortran顺序
    np.nditer(X, order="C")
    np.nditer(X, order="F")
  • 修改数组值

    • 设置writeonlyreadwrite
      • 生成可写的缓冲区数组,并在迭代完成后复制回原始 数组
      • 发出迭代结束信号,将缓冲区数据复制回原始数组
        • 支持with语句上下文管理
        • 迭代完成后手动.close()
    • 可设置allocate标志支持为空操作数分配空间

      • None参数op,其op_flags缺省设置为 ["allocate", "readwrite"]
      1
      2
      3
      with np.nditer(X, op_flags=["readwrite"]) as it:
      for x in it:
      x[...] = 0
  • 迭代一维数组而不是数组标量

    • 缺省返回最低维维度长的一维数组
    • 可以通过设置buffered扩大返回的数组长度
      • buffersize设置buffered大小,可用此参数决定 返回的数组长度
      • 返回数组长度完全由buffersize决定,与数组shape 无关
        1
        2
        3
        a = np.arange(30).reshape(5,6)
        for x in np.nditer(a, flags=["external_loop", "buffered"], buffersize=11):
        print(x, type(x))
  • 跟踪、获取索引

    1
    2
    3
    4
    it = np.nditer(a, flags=["multi_index"])
    while not it.finished:
    print(it[0], it.multi_index)
    it.iternext()
  • 以特定数据类型迭代

    • op_dtypes参数设置迭代返回的数据类型
    • 需同时设置"copy""buffered"字段
    1
    2
    for x in np.nditer(a, op_dtypes=["complex128"]):
    print(np.sqrt(x), end=" ")
  • 迭代器分配空间

    • allocate标志表示允许为操作数分配空间,即允许空 操作数
    • 若分配空间初值被使用,注意迭代前初始化 (如reduction迭代场合)
    1
    2
    3
    4
    5
    6
    7
    def square(a, ret=None):
    with np.nditer([a, ret],
    op_flags=[["readonly"], ["writeonly", "allocate"]]
    ) as it:
    for x, y in it:
    y[...] = x**2
    return ret
  • 外积(笛卡尔积)迭代

    • 设置op_axes参数指定各操作数op各维度位置、顺序

      • 迭代器负责将迭代器维度映射回各操作数维度
      • 类似于手动自由广播
      1
      2
      3
      4
      5
      6
      7
      8
      # 指定维度位置、顺序
      it = np.nditer([a,b,None], flags=["external_loop"],
      op_axes=[[0,-1,-1], [-1,0,1],None])
      # 迭代得到外积
      with it:
      for x,y,z in it:
      z[...] = x*y
      result = it.operands[2]
  • Reduction迭代

    • 触发条件:可写的操作数中元素数量小于迭代空间
      • "reduce_ok"需被设置
      • "readwrite"而不是"writeonly"被设置,即使循环 内部未读
      • 暗含"no_broadcast"必然不被设置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    ret = np.array([0])
    with np.nditer([a,b], flags=["reduce_ok", "external_loop"],
    op_flags=[["readonly"], ["readwrite"]]) as it:
    for x,y in it:
    y[...] += x
    # 或者同样设置`allocate`标志,并且在迭代器内设置初始值
    np.nditer([a, None], flags=["reduce_ok", "external_loop"],
    op_flags=[["readonly"], ["readwrite", "allocate"]],
    op_axes=[None, [0,1,-1]])
    with it:
    # 设置初始值
    it.operands[1][...] = 0
    for x, y in it:
    y[...] += x
    result = it.operands[1]

nested_iters

  • nested_iters:按维度嵌套nditer

    • 迭代参数类似nditer
    1
    2
    3
    4
    5
    i, j = np.nested_iters(X, flags=["multi_index"])
    for x in i:
    print(i.multi_index)
    for y in j:
    print("", j.multi_index, y)

flat迭代器

  • X.flat:返回C-contiguous风格迭代器np.flatiter
    • 支持切片、高级索引
    • 实质上是数组的一维视图

np.ndenumerate

  • np.ndenumerate:多维索引迭代器,返回多维索引、值元组

    1
    2
    for multi_idx, val in np.ndenumerate(X):
    pass

np.broadcast

  • np.broadcast:返回(多个)数组广播结果元组的迭代器

    • 类似广播后zip,即先将数组广播,然后将广播后元素 组合成元组作为迭代器中元素
    1
    2
    for item in np.broadcast([[1,2],[3,4]], [5,6]):
    pass

Numpy Readme

常用参数说明

  • 函数书写说明同Python全局
  • 以下常用参数如不特殊注明,按照此解释

NDArray常用参数

基本数组参数

  • size=None(1)/int/Tuple[int]

  • shape=None/int/Tuple[int]

    • 含义:NDArray形状
      • int:1维时可直接用整数表示shape
      • tuple:高维至低维指定哥维度大小
        • -1:由整个size、其余维度推断该维度大小
    • 默认:None1
  • dtype=None/str/list/dict/np.dtype/...

    • 含义:指定输出数组数据类型
      • None:保证精度情况下自动选择数据类型
      • strlistdict:可转换为数据类型
      • np.dtypenp.dtype实例
    • 默认值:None,有内部操作,选择合适、不影响精度类型
  • order="K"/"C"/"F"/"A"

    • 含义:指定数组对象(输出)内存布局、迭代顺序
      • "C":C-contiguous风格,行优先
      • "F":Fortran-contiguous风格,列优先
      • "A":除非所有参数数组均为Fortran风格,否则 为C风格
      • "K":尽量贴近已有内存布局,原为”C”/“F”方式则 保持不变,否则选择较接近的风格
    • 默认值:”C”/“K”
  • casting="same_kind","no","equiv","safe","unsafe"

    • 含义:类型转换规则
      • no:不允许任何类型转换
      • equiv:仅允许字节顺序改变
      • safe:仅允许可保证数据精度的类型转换
      • same_kind:只能允许safe或同类别类型转换
      • unsafe:允许所有类型转换
    • numpy 1.10及以上版本,缺省为"same_kind"

结果参数

  • out=None/Tuple[Array]/Array

    • 含义:保存结果的变量
      • None:由函数自行分配空间
      • tuple:需要存储多个输出结果的变量元组
      • Array:仅需要保存单个输出结果的变量元组
    • 默认:None
    • 函数自行分配空间不会初始化,即若其中某些元素未被设置 值,则其值不可预测,如
      • whereTrue时,False对应元素
  • keepdims=False/True

    • 含义:是否维持原维数
      • True:保留本应被缩减的维度,并设置维度长为1
        • 保证结果和输入操作数广播兼容
      • False:不保持维数不变
    • 默认:False
  • subok=True/False

    • 含义:是否允许数组子类作为输出
      • True:允许
      • False:不允许
    • 默认:True

标记参数

  • where=True/False/Array[bool]

    • 含义:指示符合条件、需执行操作的bool map
      • True:广播为全True,所有元素
      • False:广播为全False,所有元素都不
      • Array[bool]True表示对应位置的元素满足条件 (需要和输入操作数广播兼容)
  • weekmask="1111100"/str/list

    • 含义:指示一周内工作日
      • 字符串
        • 10按顺序表示周一到周日为、非工作日
        • 空白符、驼峰分割周一至周日全称或缩写
      • 列表:01按顺序表示周一到周日为、非工作日
  • condition=Array[bool,int]

    • 含义:指示符合条件、需要执行操作的bool map
      • Array[bool]True表示对应位置的元素满足条件
      • Array[int]:根据是否为0转换为bool数组

TensorFlow资源管理

Resources

tf.placeholder

placeholder:占位符,执行时通过feed_dict参数设置值

1
2
3
4
5
tf.placeholder(
dtype,
shape=None,
name=None
)
  • shape:并不必须,但最好设置参数方便debug
  • 需要导入数据给placeholder,可能影响程序速度
  • 方便用户替换图中值

tf.data.DataSet

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
class tf.data.DataSet:
def __init__(self)

# 从tensor slice创建`Dataset`
def from_tensor_slices(self,
?data=(?features, ?labels)
):
pass

# 从生成器创建`Dataset`
def from_generator(self,
gen,
output_types,
output_shapes
):
pass

# 迭代数据集一次,无需初始化
def make_one_shot_iterator(self):
pass

# 迭代数据集任意次,每轮迭代需要初始化
def make_initializable_iterator(self):
pass

# shuffle数据集
def shuffle(self, ?seed:int):
pass

# 重复复制数据集
def repeat(self, ?times:int):
pass

# 将数据集划分为batch
def batch(self, batch_size:int):
pass

def map(self, func:callable):
pass
  • 创建只能迭代一轮的迭代器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    iterator = dataset.make_one_shot_iterator()
    # 这里`X`、`Y`也是OPs,在执行时候才返回Tensor
    X, Y = iterator.get_next()

    with tf.Session() as sess:
    print(sess.run([X, Y]))
    print(sess.run([X, Y]))
    print(sess.run([X, Y]))
    # 每次不同的值
  • 创建可以多次初始化的迭代器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    iterator = data.make_initializable_iterator()
    with tf.Session() as sess:
    for _ in range(100):
    # 每轮重新初始化迭代器,重新使用
    sess.run(iterator.initializer)
    total_loss = 0
    try:
    while True:
    sess.run([optimizer])
    # 手动处理迭代器消耗完毕
    except tf.error.OutOfRangeError:
    pass
  • tf.datatf.placeholder适合场景对比

    • tf.data速度更快、适合处理多数据源
    • tf.placeholder更pythonic、原型开发迭代速度快

读取文件数据

可以从多个文件中读取数据

1
2
3
4
5
6
 # 文件每行为一个entry
class tf.data.TextLineDataset(filenames):
# 文件中entry定长
class tf.data.FixedLengthRecordDataset(filenames):
# 文件为tfrecord格式
class tf.data.TFRecordDataset(filenames):

tf.data.Iterator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class tf.data.Iterator:
# 获取下组迭代数据
def get_next():
pass

# 根据dtype、shape创建迭代器
@classmethod
def from_structure(self,
?dtype: type,
?shape: [int]/(int)
):
pass

# 从数据中初始化迭代器
def make_initializer(self,
?dataset: tf.data.Dataset
):
pass

TensorFlow Python IO接口

TFRecord

TFRecord格式:序列化的tf.train.Example protbuf对象

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
class tf.python_io.TFRecordWriter:
def __init__(self,
?fileanme: str,
options: tf.python_io.TFRecordOptions,
name=None
):
pass

class tf.python_io.TFRecordReader:
def __init__(self,
options: tf.python_io.TFRecordOptions,
name=None
):
pass

def read(self):
pass

### Feature/Features

```python
class tf.train.Features:
def __init__(self,
feature: {str: tf.train.Feature}
):
pass

class tf.train.Feature:
def __init__(self,
int64_list: tf.train.Int64List,
float64_list: tf.train.Float64List,
)

示例

  • 转换、写入TFRecord

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 创建写入文件
    writer = tf.python_io.TFRecord(out_file)
    shape, binary_image = get_image_binary(image_file)
    # 创建Features对象
    featurs = tf.train.Features(
    feature = {
    "label": tf.train.Feature(int64_list=tf.train.Int64List(label)),
    "shape": tf.train.Feature(bytes_list=tf.train.BytesList(shape)),
    "image": tf.train.Feature(bytes_list=tf.train.BytesList(binary_image))
    }
    )
    # 创建包含以上特征的示例对象
    sample = tf.train.Example(features=Features)
    # 写入文件
    writer.write(sample.SerializeToString())
    writer.close()
  • 读取TFRecord

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    dataset = tf.data.TFRecordDataset(tfrecord_files)
    dataset = dataset.map(_parse_function)
    def _parse_function(tf_record_serialized):
    features = {
    "labels": tf.FixedLenFeature([], tf.int64),
    "shape": tf.FixedLenFeature([], tf.string),
    "image": tf.FixedLenFeature([], tf.string)
    }
    parsed_features = tf.parse_single_example(tfrecord_serialized, features)
    return parsed_features["label"], parsed_features["shape"],
    parsed_features["image"]

其他函数

TensorFlow控制算符

控制OPs

Neural Network Building Blocks

tf.softmax

tf.Sigmod

tf.ReLU

tf.Convolution2D

tf.MaxPool

Checkpointing

tf.Save

tf.Restore

Queue and Synchronization

tf.Enqueue

tf.Dequeue

tf.MutexAcquire

tf.MutexRelease

Control Flow

tf.count_up_to

tf.cond

predTrue,执行true_fn,否则执行false_fn

1
2
3
4
5
tf.cond(
pred,
true_fn=None,
false_fn =None,
)

tf.case

tf.while_loop

tf.group

tf.Merge

tf.Switch

tf.Enter

tf.Leave

tf.NextIteration

TensorFlow操作符

Tensor

张量:n-dimensional array,类型化的多维数组

  • TF使用Tensor表示所有的数据
  • Tensor包含一个静态类型rank、一个shape
  • TF会将python原生类型转换为相应的Tensor
    • 0-d tensor:scalar
    • 1-d tensor:vector,1d-array
    • 2-d tensor:matrix,2d-array

Data Type

  • TF被设计为和numpy可以无缝结合

    • TF的变量类型基于numpy变量类型:tf.int32==np.int32
    • bool、numeric等大部分类型可以不加转换的使用TF、np 变量类型
    • TF、np中string类型不完全一样,但TF仍然可以从numpy 中导入string数组,但是不能在numpy中指定类型
  • 但尽量使用TF变量类型

    • python原生类型:没有细分类型,TF需要推断类型
    • numpy类型:numpy不兼容GPU,也不能自动计算衍生类型
数据类型 说明
tf.float16 16-bit half-precision floating-point
tf.float32 32-bit single-presicion floating-point
tf.float64 64-bit double-presicion floating-point
tf.bfloat16 16-bit truncated floating-point
tf.complex64 64-bit single-presicion complex
tf.complex128 128-bit double-presicion complex
tf.int8 8-bit signed integer
tf.uint8 8-bit unsigned integer
tf.int16
tf.uint16
tf.int32
tf.int64
tf.bool
tf.string
tf.qint8 quantized 8-bit signed integer
tf.quint8
tf.qint16
tf.quint16
tf.qint32
tf.resource handle to a mutable resource

Constant OPs

tf.constant

1
2
3
4
5
6
7
def constant(
value,
dtype=none,
shape=none,
name="Const",
verify_shape=False
)

同值常量OPs

  • zeros:类似np中相应函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # `np.zeros`
    def tf.zeros(
    shape,
    dtype=tf.float32,
    name=None
    )

    # `np.zores_like`
    def tf.zeros_like(
    input_tensor,
    dtype=None,
    name=None,
    optimizeTrue
    )
    • 若没有指明dtype,根据input_tensor确定其中值
      • 对数值型为0.0
      • 对bool型为False
      • 对字符串为b''
  • ones:类似np中相应函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# `np.ones`
def tf.ones(
shape,
dtype=tf.float32,
name=None
)

# `np.ones_like`
def tf.ones_like(
input_tensor,
dtype=None,
name=None,
optimize=True
)
- 若没有指明`dtype`,根据`input_tensor`确定 - 对数值型为`0.0` - 对bool型为`True` - 对字符串报错
  • fill:以value填充dims给定形状

    1
    2
    3
    4
    5
    6
    # `np.fill`
    def tf.fill(
    dims,
    value,
    name=None
    )

列表常量OPs

  • tensor列表不能直接for语句等迭代
  • tf.lin_spacestartstop直接均分为num部分

    1
    2
    3
    4
    5
    6
    7
    # `np.linspace`
    def lin_space(
    start,
    stop,
    num,
    name=None
    )
  • tf.rangestartstop间等间隔delta取值

    1
    2
    3
    4
    5
    6
    7
    8
    # `np.arange`
    def tf.range(
    start,
    limit=None,
    delta=1,
    dtype=None,
    name="range"
    )

随机常量OPs

  • seed:设置随机数种子

    1
    2
    3
    # np.random.seed
    def tf.set_random_seed(seed):
    pass
  • random:随机生成函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    def tf.random_normal()
    def tf.truncated_normal(
    ?avg=0/int/(int),
    stddev=1.0/float,
    seed=None/int,
    name=None
    ):
    pass

    def tf.random_uniform(
    shape(1d-arr),
    minval=0,
    maxval=None,
    dtype=tf.float32,
    seed=None/int,
    name=None/str
    ):
    pass

    def tf.random_crop()

    def tf.multinomial()

    def tf.random_gamma()
  • shuffle

    1
    def tf.random_shuffle()

运算OPs

元素OPs

四则运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

def add(x, y, name=None)
def subtract(x, y, name=None)
def sub(x, y, name=None)
def multiply(x, y, name=None)
def mul(x, y, name=None)
# 加、减、乘

def floordiv(x, y, name=None)
def floor_div(x, y, name=None)
def div(x, y, name=None)
def truncatediv(x, y, name=None)
# 地板除

def divide(x, y, name=None)
def truediv(x, y, name=None)
# 浮点除

def realdiv(x, y, name=None)
# 实数除法,只能用于实数?

def add_n(input, name=None)
# `input`:list-like,元素shapetype相同
# 累加`input`中元素的值

逻辑运算

1
2
3
def greater()
def less()
def equal()

数学函数

1
2
3
4
5
6
7
8
9
10
11
def exp()
def log()
def square()
def round()
def sqrt()
def rsqrt()
def pow()
def abs()
def negative()
def sign()
def reciprocal() # 倒数

列表运算OPs

1
2
3
4
5
6
def tf.Concat()
def tf.Slice()
def tf.Split()
def tf.Rank()
def tf.Shape()
def tf.Shuffle()

矩阵OPs

1
2
3
4
def tf.MatMul()
def tf.MatrixInverse()
def tf.MatrixDeterminant()
def tf.tensordot() # 矩阵点乘

梯度OPs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def tf.gradients(				# 求`y`对`[xs]`个元素偏导
ys: tf.OPs,
xs: tf.OPs/[tf.OPs],
grad_ys=None,
name=None
)
def tf.stop_gradient(
input,
name=None
)
def clip_by_value(
t,
clip_value_min,
clip_value_max,
name=None
)
def tf.clip_by_norm(
t,
clip_norm,
axes=None,
name=None
)

Variable

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
class Variable:
def __init__(self,
init_value=None,
trainable=True,
collections=None,
validata_shape=True,
caching_device=None,
name=None,
variable_def=None,
dtype=None,
expected_shape=None,
import_scope=None,
constraint=None
)

# 初始化变量
# `sess.run`其即初始化变量
def intializer(self):
pass

# 读取变量值
def value(self):
pass

# 获取变量初始化值,其他变量调用、声明依赖该变量
def initilized_value(self):
pass

# 计算、获取变量值,类似`sess.run(OP)`
def eval(self):
pass

# 给变量赋值
# `assgin`内部有初始化Variable,所以有时可以不用初始化
def assign(self):
pass
#`assgin_add`等依赖于原始值,不会初始化变量
def assign_add(self, ?dec)
def assign_divide(self, ?dec)
  • Variable是包含很多方法的类

    • 其中方法OPs和一般的OP一样,也需要在Session中执行 才能生效
    • Variable必须在会话中初始化后,才能使用
    • 会话维护自身独立Variable副本,不相互影响
  • Variable和图分开存储,甚至是存储在独立参数服务器上

    • 存储大量数据也不会拖慢图载入速度
    • 通常用于存储训练过程中weight、bias、维护图执行过程 中状态信息
  • constants是常数OPs

    • 存储在图中:每次载入图会同时被载入,过大的constants 会使得载入图非常慢
    • 所以最好只对原生类型使用constants

Variable创建

tf.get_variable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def get_variable(
name,
shape=None,
dtype=None,
initializer=None,
regularizer=None,
trainable=True,
collections=None,
caching_device=None,
partitioner=None,
validate_shape=True,
use_resource=None,
custom_getter=None,
constraint=None
)
  • 此封装工厂方法相较于直接通过tf.Variable更好
    • 若变量已设置,可通过变量名获取变量,方便变量共享
    • 可以提供更多的参数定制变量值
1
2
3
4
5
6
7
8
9
10
11
	# `tf.Variable`创建变量
s = tf.Variable(2, name="scalar")
m = tf.Variable([[0,1], [2,3]], name="matrix")
w = tf.Variable(tf.zeros([784, 10]))
# `tf.get_variable`创建、获取变量
s = tf.get_variable("scalar", initializer=tf.constant(2))
m = tf.get_variable("matrix", initializer=tf.constant([[0,1], [2,3]])
W = tf.get_variable("big_matrix",
shape=(784, 10),
initializer=tf.zeros_initializer()
)

Variable初始化

1
2
3
4
5
6
7
with tf.Session() as sess:
# 初始化所有Variables
sess.run(tf.global_variable_initialier())
# 初始化变量子集
sess.run(tf.variable_initializer([s, m])
# 初始化指定单个变量
sess.run(s.initializer)
  • 若某Variable依赖其他Variable,需要使用 initialized_value指明依赖,确保依赖线性初始化

    1
    2
    3
    W = tr.Variable(tf.truncated_normal([700, 100])
    # 指明依赖,保证依赖线性初始化
    U = tf.Variable(W.initialized_value() * 2)