Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
N
NiuTrans.Tensor
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
Emmay
NiuTrans.Tensor
Commits
969b7054
Commit
969b7054
authored
Jul 06, 2018
by
linye
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
删除 manual.md
parent
1d44c72a
隐藏空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
0 行增加
和
199 行删除
+0
-199
doc/manual.md
+0
-199
没有找到文件。
doc/manual.md
deleted
100644 → 0
查看文件 @
1d44c72a
# NiuTrans.Tensor张量计算库
## NiuTrans.Tensor
NiuTrans.Tensor是小牛开源项目所开发的一个工具包,提供了完整的张量定义及计算功能,可以被用于深度学习相关研究及工业系统的开发。NiuTrans.Tensor具有以下特点:
*
简单小巧,易于修改
*
c语言编写,代码高度优化
*
同时支持CPU和GPU设备
*
丰富的张量计算接口
*
支持C/C++、Python等调用方式
## 安装NiuTrans.Tensor
## 什么是张量
在计算机科学中,张量(Tensor)通常被定义为$n$维空间中的一种量,它具有$n$个分量,这种量本质上是一个多维数组( multidimensional array)。张量的阶或秩是这个多维数组的维度,或者简单理解为索引张量里的每个元素所需要的索引个数。通常来说,0阶张量被定义为标量(Scalar),1阶张量被定义为向量(vector),而2阶张量被定义为矩阵(matrix)。比如,在一个三维空间中,1阶张量就是空间中点所表示的向量$(x,y,z)$,其中$x$、$y$、$z$分别表示这个点在三个轴上的坐标。
张量是一种高效的数学建模工具,它可以将复杂的问题通过统一、简洁的方式进行表达。比如,姜英俊同学做饭需要2斤牛肉、5斤土豆,市场上牛肉每斤32元、土豆每斤2元,那么购买这些食物总共花费$2
\t
imes 32 + 5
\t
imes 2 = 74$元。如果用张量来描述,我们可以用一个1阶张量$a=(2,5)$表示所需不同食物的重量。然后用另一个1阶张量$b=(32,2)$表示不同食物的价格。最后,我们用一个0阶张量$c$表示购买这些食物的总价,计算如下
$$
\b
egin{aligned}
c & = a
\t
imes b^T
\\
& =
\l
eft(
\b
egin{matrix}2 & 5
\e
nd{matrix}
\r
ight)
\t
imes
\l
eft(
\b
egin{matrix}32
\\
2
\e
nd{matrix}
\r
ight)
\\
& = 2
\t
imes 32 + 5
\t
imes 2
\\
& = 74
\e
nd{aligned}
$$
其中$b^T$表示行向量$b$的转置 - 列向量,$
\t
imes$表示向量的乘法。第二天,姜英俊同学换了一个市场,这里牛肉每斤35元、土豆每斤1元。如果要知道在两个市场分别购物的总价,可以把$b$重新定义为一个2阶张量$
\l
eft(
\b
egin{matrix}12 & 2
\\
35 & 1
\e
nd{matrix}
\r
ight)$,总价$c$定义为一个2阶张量。同样有
$$
\b
egin{aligned}
c & = a
\t
imes b^T
\\
& =
\l
eft(
\b
egin{matrix}2 & 5
\e
nd{matrix}
\r
ight)
\t
imes
\l
eft(
\b
egin{matrix}12 & 35
\\
2 & 1
\e
nd{matrix}
\r
ight)
\\
& =
\l
eft(
\b
egin{matrix}74 & 75
\e
nd{matrix}
\r
ight)
\e
nd{aligned}
$$
即,在两个市场分别花费74元和75元。可以看出,利用张量可以对多样、复杂的问题进行建模,比如,可以进一步扩展上述问题中$a$、$b$、$c$的定义,把它们定义成更高阶的张量,处理不同时间、不同市场、不同菜谱的情况,但是不论情况如何变化,都可以用同一个公式$c = a
\t
imes b^T$来描述问题。
许多现实世界的问题都可以被描述为张量表达式(expression),也就是把张量的组合、计算描述为算数表达式。这种建模方式也构成了现代神经网络模型及深度学习方法的基础。在许多机器学习工具中,张量计算已经成为了神经网络前向、反向传播等过程的基本单元,应用十分广泛。
## 如何定义张量
如果你是一名C/C++或者Python的使用者,那么在程序中使用NiuTrans.Tensor定义张量将非常简单。首先,下载NiuTrans.Tensor的工具包(source???),并加压到任意目录,比如~/NTS目录。我们会在NTS这个目录中有找到source子目录,它是存放源代码的目录。对于source子目录的结构,信息如下:
*
~/NTS/source/XTensor.h - 定义了张量结构XTensor,以及构建和销毁XTensor的接口
*
~/NTS/source/core - 存放张量计算的函数声明及函数体实现的源文件
*
~/NTS/source/function - 存放各种激活函数的源文件
*
~/NTS/source/test - 存放单元测试的源文件
*
~/NTS/source/
*
.h(cpp) - 与张量定义不相关,后文介绍 :)
以C/C++为例,仅需要在源程序中引用XTensor.h头文件就可以完成张量的定义。下面是一个简单的示例程序sample.cpp
<pre><code>
#inlucde "XTensor.h" // 引用XTensor定义的头文件
using namepsace nt; // 使用XTensor所在的命名空间nt
int main(int argc, const char
**
argv)
{
// 声明一个变量tensor,它的类型是XTensor
XTensor tensor;
// 初始化这个变量为50列*100行的矩阵(2阶张量)
InitTensor2D(&tensor, 50, 100, X_FLOAT);
// 之后可以使用张量tensor了
return 0;
}
</code></pre>
下一步,编译以上源程序,这个过程需要指定XTensor.h头文件所在目录。比如,使用g++编译sample.cpp(如果你使用的是visual studio,请看这里???)
<pre><code>
g++ sample.cpp -I~/NTS/source -o sample
</code></pre>
在sample.cpp中使用了XTensor,它是NiuTrans.Tensor里的一个类,这个类定义了张量所需的数据结构。我们可以使用这个类完成对张量的计算、拷贝等各种操作。XTensor类型的变量被声明后,这个变量需要被初始化,或者说被真正指定为一个张量,比如,指定张量各个维度的大小、张量中每个单元的数据类型、给张量分配内存空间等。InitTensor2D()就是一个张量初始化函数,它把张量初始化为一个矩阵,有四个参数:指向被初始化的张量的指针,矩阵的列数,矩阵的行数,数据单元的类型。这里X_FLOAT,是NiuTrans.Tensor自定义的枚举类型,它表示单精度浮点数。我们也可以使用X_INT或者X_DOUBLE,将数据类型指定为32bit整数或者双精度浮点数。
NiuTrans.Tensor也提供了其它方式定义张量。比如可以直接调用一个函数完成张量的创建,而且可以显性释放张量。下面是一段示例代码(sample2.cpp):
<pre><code>
#inlucde "XTensor.h" // 引用XTensor定义的头文件
using namepsace nt; // 使用XTensor所在的命名空间nt
int main(int argc, const char
**
argv)
{
// 构建一个单精度浮点类型张量,它是一个50列
*
100行的矩阵
XTensor
*
tensor = NewTensor2D(&tensor, 50, 100, X_FLOAT);
// 之后可以使用张量tensor了
// 释放这个张量
DelTensor(tensor);
return 0;
}
</code></pre>
sample2.cpp中使用的NewTensor2D和DelTensor是一组函数,前者生成张量并返回指向这个张量的指针,后者释放指针所指向张量的内容。这种方法比较适合C语言风格的开发。
> 注意,在NiuTrans.Tensor中所有张量默认都是“稠密”张量,也就是张量中所有的单元都会被分配空间,而且这些空间是连续的。有些情况下,张量里的单元仅有少数为非零单元,对于这类张量,可以使用“稀疏"的表示方法,这样可以有效的节省存储空间。
如果要定义稀疏张量,需要在原有的参数基础上额外指定一个参数 - 稠密度。所谓稠密度是指非零单元的比例,他是介于0和1之间的一个实数,0表示所有单元全为零,1表示全为非零单元。默认所有张量的稠密度都是1。下面是不同类型张量的定义方法示例(sample3.cpp)
<pre><code>
#inlucde "XTensor.h" // 引用XTensor定义的头文件
using namepsace nt; // 使用XTensor所在的命名空间nt
int main(int argc, const char
**
argv)
{
// 构建一个单精度浮点类型张量,它是一个50列
*
100行的矩阵
// 这个张量是稠密的
XTensor
*
tensor0 = NewTensor2D(&tensor, 50, 100, X_FLOAT);
// 构建一个单精度浮点类型张量,它是一个50列*100行的矩阵
// 这个张量是稠密的
XTensor * tensor1 = NewTensor2D(&tensor, 50, 100, X_FLOAT, 1.0F);
// 构建一个单精度浮点类型张量,它是一个50列*100行的矩阵
// 这个张量是稀疏的,有10%的单元非零
XTensor * tensor2 = NewTensor2D(&tensor, 50, 100, X_FLOAT, 0.1F);
// 之后可以使用张量tensor0,tensor1和tensor2了
// 释放这些张量
DelTensor(tensor0);
DelTensor(tensor1);
DelTensor(tensor2);
return 0;
}
</code></pre>
以下是关于张量定义的基础函数:
功能 | 函数 | 参数
-: | - | -
初始化张量 | void InitTensor(
<br>
XTensor
* tensor, const int myOrder, <br> const int *
myDimSize, const float myDenseRatio,
<br>
const TENSOR_DATA_TYPE myDataType = X_FLOAT,
<br>
const int myDevID = -1, XMem
*
myMem = NULL)
<br>
<br>
<br>
| tensor - 指向被初始化张量的指针
<br>
myOrder - 张量的维度
<br>
myDimSize - 张量每一维的大小,索引0表示第一维
<br>
myDenseRatio - 张量的稠密度,1表示稠密张量
<br>
myDataType - 张量的数据类型
<br>
myDevID - 张量所在的设备ID
<br>
myMem - 张量所使用的内存池
初始化稠密张量 | void InitTensor(
<br>
XTensor
* tensor, const int myOrder, <br> const int *
myDimSize,
<br>
const TENSOR_DATA_TYPE myDataType = X_FLOAT,
<br>
const int myDevID = -1, XMem
*
myMem = NULL)
<br>
<br>
| tensor - 指向被初始化张量的指针
<br>
myOrder - 张量的维度
<br>
myDimSize - 张量每一维的大小,索引0表示第一维
<br>
myDataType - 张量的数据类型
<br>
myDevID - 张量所在的设备ID
<br>
myMem - 张量所使用的内存池
创建空张量 | XTensor
*
NewTensor() | N/A
创建张量 | XTensor
* NewTensor(<br>const int myOrder, <br> const int *
myDimSize, const float myDenseRatio,
<br>
const TENSOR_DATA_TYPE myDataType = X_FLOAT,
<br>
const int myDevID = -1, XMem
*
myMem = NULL)
<br>
<br>
| myOrder - 张量的维度
<br>
myDimSize - 张量每一维的大小,索引0表示第一维
<br>
myDenseRatio - 张量的稠密度,1表示稠密张量
<br>
myDataType - 张量的数据类型
<br>
myDevID - 张量所在的设备ID
<br>
myMem - 张量所使用的内存池
创建稠密张量 | XTensor
* NewTensor(<br>const int myOrder, <br> const int *
myDimSize,
<br>
const TENSOR_DATA_TYPE myDataType = X_FLOAT,
<br>
const int myDevID = -1, XMem
*
myMem = NULL)
<br>
| myOrder - 张量的维度
<br>
myDimSize - 张量每一维的大小,索引0表示第一维
<br>
myDataType - 张量的数据类型
<br>
myDevID - 张量所在的设备ID
<br>
myMem - 张量所使用的内存池
销毁张量 | void DelTensor(const XTensor
*
tensor) | tensor - 指向要被销毁的张量的指针
上述函数中需要说明的是
*
设备ID是指张量所申请的空间所在CPU或者GPU设备的编号,-1表示CPU
*
XMem是NiuTrans.Tensor中定一个内存/显存池类,它负责内存(或显存)的统一管理。关于设备ID和XMem的进一步说明,请参见下一节内容。
*
TENSOR_DATA_TYPE定义了张量的数据类型,包括:
类型 | 说明
-
| -
X_INT | 32bit整数
X_FLOAT | 32bit浮点数
X_DOUBLE | 64bit浮点数
X_INT8 | 8bit整数(计划支持)
X_FLOAT16 | 16bit浮点数(计划支持)
此外,NiuTrans.Tensor也提供了更多种类的张量初始化和创建方法:
功能 | 函数 | 参数
-: | - | -
初始化为稠密向量 | void InitTensor1D(
<br>
XTensor
* tensor, const int num, <br> const TENSOR_DATA_TYPE myDataType = X_FLOAT, <br>const int myDevID = -1, XMem *
myMem = NULL)
<br>
<br>
| tensor - 指向被初始化张量的指针
<br>
num - 向量维度大小
<br>
myDataType - 张量的数据类型
<br>
myDevID - 张量所在的设备ID
<br>
myMem - 张量所使用的内存池
初始化为稠密矩阵 | void InitTensor2D(
<br>
XTensor
* tensor, const int colNum, const int rowNum, <br> const TENSOR_DATA_TYPE myDataType = X_FLOAT, <br>const int myDevID = -1, XMem *
myMem = NULL)
<br>
<br>
<br>
| tensor - 指向被初始化张量的指针
<br>
colNum - 矩阵列数
<br>
rowNum - 矩阵行数
<br>
myDataType - 张量的数据类型
<br>
myDevID - 张量所在的设备ID
<br>
myMem - 张量所使用的内存池
初始化为3维稠密张量 | void InitTensor3D(
<br>
XTensor
* tensor, <br> const int d0, const int d1, const int d2, <br> const TENSOR_DATA_TYPE myDataType = X_FLOAT, <br>const int myDevID = -1, XMem *
myMem = NULL)
<br>
<br>
<br>
| tensor - 指向被初始化张量的指针
<br>
d0 - 张量第一维大小
<br>
d1 - 张量第二维大小
<br>
d2 - 张量第三维大小
<br>
myDataType - 张量的数据类型
<br>
myDevID - 张量所在的设备ID
<br>
myMem - 张量所使用的内存池
初始化为4维稠密张量 | void InitTensor4D(
<br>
XTensor
* tensor, <br> const int d0, const int d1, const int d2, const int d3, <br> const TENSOR_DATA_TYPE myDataType = X_FLOAT, <br>const int myDevID = -1, XMem *
myMem = NULL)
<br>
<br>
<br>
<br>
| tensor - 指向被初始化张量的指针
<br>
d0 - 张量第一维大小
<br>
d1 - 张量第二维大小
<br>
d2 - 张量第三维大小
<br>
d3 - 张量第四维大小
<br>
myDataType - 张量的数据类型
<br>
myDevID - 张量所在的设备ID
<br>
myMem - 张量所使用的内存池
初始化为5维稠密张量 | void InitTensor5D(
<br>
XTensor
* tensor, <br> const int d0, const int d1, const int d2, <br> const int d3, const int d4, <br> const TENSOR_DATA_TYPE myDataType = X_FLOAT, <br>const int myDevID = -1, XMem *
myMem = NULL)
<br>
<br>
<br>
<br>
| tensor - 指向被初始化张量的指针
<br>
d0 - 张量第一维大小
<br>
d1 - 张量第二维大小
<br>
d2 - 张量第三维大小
<br>
d3 - 张量第四维大小
<br>
d4 - 张量第五维大小
<br>
myDataType - 张量的数据类型
<br>
myDevID - 张量所在的设备ID
<br>
myMem - 张量所使用的内存池
创建稠密向量 | XTensor
* NewTensor1D(<br>const int num, <br> const TENSOR_DATA_TYPE myDataType = X_FLOAT, <br>const int myDevID = -1, XMem *
myMem = NULL)
<br>
| num - 向量维度大小
<br>
myDataType - 张量的数据类型
<br>
myDevID - 张量所在的设备ID
<br>
myMem - 张量所使用的内存池
创建稠密矩阵 | XTensor
* NewTensor2D(<br>const int colNum, const int rowNum, <br> const TENSOR_DATA_TYPE myDataType = X_FLOAT, <br>const int myDevID = -1, XMem *
myMem = NULL)
<br>
<br>
| colNum - 矩阵列数
<br>
rowNum - 矩阵行数
<br>
myDataType - 张量的数据类型
<br>
myDevID - 张量所在的设备ID
<br>
myMem - 张量所使用的内存池
创建3维稠密张量 | XTensor
* NewTensor3D(<br> const int d0, const int d1, const int d2, <br> const TENSOR_DATA_TYPE myDataType = X_FLOAT, <br>const int myDevID = -1, XMem *
myMem = NULL)
<br>
<br>
<br>
| d0 - 张量第一维大小
<br>
d1 - 张量第二维大小
<br>
d2 - 张量第三维大小
<br>
myDataType - 张量的数据类型
<br>
myDevID - 张量所在的设备ID
<br>
myMem - 张量所使用的内存池
创建4维稠密张量 | XTensor
* NewTensor4D(<br>const int d0, const int d1, const int d2, const int d3, <br> const TENSOR_DATA_TYPE myDataType = X_FLOAT, <br>const int myDevID = -1, XMem *
myMem = NULL)
<br>
<br>
<br>
<br>
| d0 - 张量第一维大小
<br>
d1 - 张量第二维大小
<br>
d2 - 张量第三维大小
<br>
d3 - 张量第四维大小
<br>
myDataType - 张量的数据类型
<br>
myDevID - 张量所在的设备ID
<br>
myMem - 张量所使用的内存池
创建5维稠密张量 | XTensor
* NewTensor5D(<br>const int d0, const int d1, const int d2, <br> const int d3, const int d4, <br> const TENSOR_DATA_TYPE myDataType = X_FLOAT, <br>const int myDevID = -1, XMem *
myMem = NULL)
<br>
<br>
<br>
<br>
| d0 - 张量第一维大小
<br>
d1 - 张量第二维大小
<br>
d2 - 张量第三维大小
<br>
d3 - 张量第四维大小
<br>
d4 - 张量第五维大小
<br>
myDataType - 张量的数据类型
<br>
myDevID - 张量所在的设备ID
<br>
myMem - 张量所使用的内存池
其它问题??
*
程序编译,是直接引用源文件还是引用库
*
是否需要改变环境变量
*
命名空间是nt还是ntts,还是nts
## 设备及内存池
## 访问张量中的内容
## 张量计算
### 加法(Sum)
### 缩放和偏移(Scale and Shift)
## 高级技巧
## 实例1:矩阵乘法
## 实例2:前馈神经网络
## 实例3:循环神经网络
## 致谢
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论