1.关于Program
- #layer表示一个独立的计算逻辑,通常包含一个或多个op,layers.relu表示relu运算;layers.pool2d表示pool操作。layer有输入输出(variable)
- #Variable表示一个变量,变量可以是一个张量Tensor,Variable进入layer计算,然后layer返回Variable
- #program包含Variable定义的多个变量和layer定义的多个计算。Program是顺序执行的
- #Executor用来执行Program,Executor会一次性执行Program中定义的所有运算。可以通过feed提供Program的输出数据,通过fetch_list获取输出数据
5
from paddle import fluid
#两个Variable,后台生成Program
x = fluid.layers.fill_constant(shape=[1], dtype='int64', value=5)
y = fluid.layers.fill_constant(shape=[1], dtype='int64', value=6)
z = x+y
#生成执行器
exe = fluid.Executor(fluid.CPUPlace())
#[0]表示取出第一个元素,不然还会打印类型
m=exe.run(fluid.default_main_program(), fetch_list=[z])[0]
print(m)
输出
[11]
2.paddle.nn
这是一个跟定义网络相关很大的API
不用fluid定义网络,用paddle.nn这是一个动态图
import paddle
# Sequential形式组网
mnist = paddle.nn.Sequential(
paddle.nn.Flatten(),
paddle.nn.Linear(784, 512),
paddle.nn.ReLU(),
paddle.nn.Dropout(0.2),
paddle.nn.Linear(512, 10)
)
#姑且认为是(sampels,channels,rows,cols)
info = paddle.summary(mnist,(1,28,28))
print(info)
输出:
---------------------------------------------------------------------------
Layer (type) Input Shape Output Shape Param #
===========================================================================
Flatten-1 [[1, 28, 28]] [1, 784] 0
Linear-1 [[1, 784]] [1, 512] 401,920
ReLU-1 [[1, 512]] [1, 512] 0
Dropout-1 [[1, 512]] [1, 512] 0
Linear-2 [[1, 512]] [1, 10] 5,130
===========================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
---------------------------------------------------------------------------
Input size (MB): 0.00
Forward/backward pass size (MB): 0.02
Params size (MB): 1.55
Estimated Total Size (MB): 1.57
我觉得这里的标号1就是指得channels,然后(784+1)*512=401920
layer表示容器——paddle.nn.layer
paddle.nn包含卷积层,池化层,Padding层,激活层,循环神经网络层等
如果想用class类定义的话,一定要注意,__init__做到的仅仅是初始化,真正重要的是forward,forward定义了整个前向网络
import paddle
# Layer类继承方式组网
class Mnist(paddle.nn.Layer):
def __init__(self):
super(Mnist, self).__init__()
self.flatten = paddle.nn.Flatten()
self.linear_1 = paddle.nn.Linear(784, 512)
self.linear_2 = paddle.nn.Linear(512, 10)
self.relu = paddle.nn.ReLU()
self.dropout = paddle.nn.Dropout(0.2)
def forward(self, inputs):
y = self.flatten(inputs)
y = self.linear_1(y)
y = self.relu(y)
y = self.dropout(y)
y = self.linear_2(y)
return y
mnist_2 = Mnist()
info2 = paddle.summary(mnist_2,(1,28,28))
print(info2)
输出为:
---------------------------------------------------------------------------
Layer (type) Input Shape Output Shape Param #
===========================================================================
Flatten-1 [[1, 28, 28]] [1, 784] 0
Linear-1 [[1, 784]] [1, 512] 401,920
ReLU-1 [[1, 512]] [1, 512] 0
Dropout-1 [[1, 512]] [1, 512] 0
Linear-2 [[1, 512]] [1, 10] 5,130
===========================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
---------------------------------------------------------------------------
Input size (MB): 0.00
Forward/backward pass size (MB): 0.02
Params size (MB): 1.55
Estimated Total Size (MB): 1.57
---------------------------------------------------------------------------
{'total_params': 407050, 'trainable_params': 407050}
只要看结果中的层顺序就可以发现和forward的定义是相同的。
paddle中也是有高层API的,就像是tensorflow中的Keras。同样会有Model.fit(),Model.evaluate(),Model.predict()
3.paddle中的softmax
paddle.nn.functional.softmax(x, axis=-1)
输入x的axis维将会被置换到最后一维
axis=-1:横过来的和为1
axis=1:竖过来的和为1
#首先是将list转换为np.array形式,然后将array转换为tensor形式,注意数据类型,最终调用softmax函数输出,由于axis=-1,所以输出就是横过来和为1
x = [[[1,9,3],[8,3,4]]]
x = np.array(x)
x = paddle.to_tensor(x,dtype='float32')
print(x)
print(paddle.nn.functional.softmax(x,axis=-1))
输出为:
Tensor(shape=[1, 2, 3], dtype=float32, place=CPUPlace, stop_gradient=True,
[[[1., 9., 3.],
[8., 3., 4.]]])
Tensor(shape=[1, 2, 3], dtype=float32, place=CPUPlace, stop_gradient=True,
[[[0.00033452, 0.99719369, 0.00247180],
[0.97555870, 0.00657326, 0.01786798]]])
如果是axis=1,就是列的求和为1
输入:
x = [[[1,9,3],[8,3,4]]]
x = np.array(x)
x = paddle.to_tensor(x,dtype='float32')
print(x)
print(paddle.nn.functional.softmax(x,axis=1))
输出:
Tensor(shape=[1, 2, 3], dtype=float32, place=CPUPlace, stop_gradient=True,
[[[1., 9., 3.],
[8., 3., 4.]]])
Tensor(shape=[1, 2, 3], dtype=float32, place=CPUPlace, stop_gradient=True,
[[[0.00091105, 0.99752742, 0.26894143],
[0.99908900, 0.00247262, 0.73105860]]])
回过头来看CartpoleModel的前向网络结构:
import paddle
import paddle.nn as nn
import paddle.nn.functional as F
import parl
class CartpoleModel(paddle.nn.Layer):
def __init__(self):
super(CartpoleModel, self).__init__()
hid1_size = 2 * 10
self.fc1 = nn.Linear(10, 512)
self.fc2 = nn.Linear(512, 2)
def forward(self, x):
out = paddle.tanh(self.fc1(x))
prob = F.softmax(self.fc2(out), axis=-1)
return prob
mnist_2 = CartpoleModel()
info2 = paddle.summary(mnist_2,(1,28,10))
print(info2)
注意:这里的10和10一定是对应的,512就是中间的神经元,2表示输出的神经元个数。
输出:
---------------------------------------------------------------------------
Layer (type) Input Shape Output Shape Param #
===========================================================================
Linear-1 [[1, 28, 10]] [1, 28, 512] 5,632
Linear-2 [[1, 28, 512]] [1, 28, 2] 1,026
===========================================================================
Total params: 6,658
Trainable params: 6,658
Non-trainable params: 0
---------------------------------------------------------------------------
Input size (MB): 0.00
Forward/backward pass size (MB): 0.11
Params size (MB): 0.03
Estimated Total Size (MB): 0.14
---------------------------------------------------------------------------
{'total_params': 6658, 'trainable_params': 6658}
会发现这里的网络层中并没有激活层的信息。
4.Program
默认情况下,Paddle内部默认含有 default_startup_program 和 default_main_program ,它们共享参数。 default_startup_program 只运行一次来初始化参数, default_main_program 在每个mini batch中运行并更新权重。
5.paddle.static
静态图专用的API
6.paddle.static.program_guard
将with block里的算子和变量添加进指定的全局主程序(main program)和启动程序(startup program)
配合With语句将block里的算子Op和变量添加到指定的全局主程序(main program)和启动程序(startup program)
7.paddle.static.nn.fc
paddle.static.nn.fc(x, size)
在神经网络中构建一个全连接层。
- x(Tensor):是一个多维Tensor或多个Tensor组成的list,每个输入Tensor的维度至少是2,数据类型可以为float16,32或者64
- size(int):全连接层输出单元的数目,即输出Tensor的特征维度
import paddle
#使用静态图
paddle.enable_static()
main_program = paddle.static.Program()
startup_program = paddle.static.Program()
with paddle.static.program_guard(main_program, startup_program):
data = paddle.static.data(name='image', shape=[None, 784, 784],dtype='float32')
hidden = paddle.static.nn.fc(x=data, size=10, activation='relu')
########################################
意义很明显
8.paddle.static.data
该OP会在全局block中创建变量(Tensor),该全局变量可被计算图中的算子(operator)访问。
paddle.static.data(name, shape, dtype=None, lod_level=0)
- name (str)- 被创建的变量的名字 shape (list|tuple)声明维度信息的list或tuple。可以在某个维度上设置None或-1,以指示该维度可以是任何大小。例如,将可变batchsize设置为None或-1。
- dtype (np.dtype|str,可选)-数据类型,支持bool,float16,float32,float64,int8,int16,int32,int64,uint8。默认值为None。当dtype 为None时, dtype 将通过 padle.get_default_dtype() 获取全局类型。
比如:
x = paddle.static.data(name='x', shape=[3,2,1])
x是被创建的变量的名字。注意:x是变量!!!!只是个Variable
shape是被x的维度
返回的是一个Tensor,全局变量,可以进行数据访问
#var x : LOD_TENSOR.shape(3, 2, 1).dtype(float32).stop_gradient(True)
#########################
这句话的意思就是定义了一个Variable X,x的形状是[3,2,1],但是此时X只是一个定义。相当于int a这种,那就是说只有shape=[3,2,1]的数据才能送给x
###########################
y = paddle.static.data(name='y', shape=[-1, 2, 1], dtype='float32')
############################
这里定义了一个y,shape的第一个元素是-1,也就是说不管什么形状的数组都能给y赋值。
然后再用paddle做tensor的加法
z = x + y
这里已经定义了z,打印的输出为:
#var tmp_0 : LOD_TENSOR.shape(3, 2, 1).dtype(float32).stop_gradient(False)
#########################
首先用feed_data给Variable X和Y进行赋值,*****注意feed_data的shape是和X一致的。
#########################
feed_data = np.ones(shape=[3, 2, 1], dtype=np.float32)
exe = paddle.static.Executor(paddle.framework.CPUPlace())
out = exe.run(paddle.static.default_main_program(),
feed={
'x': feed_data,
'y': feed_data
},
fetch_list=[z.name])
##都是加了name的
# np-ndarray of shape=[3, 2, 1], dtype=float32, whose elements are 2
print(out)