@mzhang
最近在太极官网上,看了Dr zhang写的一篇关于使用可微分sph模型实现训练魔法喷泉的博客。
觉得使用一个NN近似的控制器来控制喷泉击中物体很有趣,然后又看了在github上公开的代码。但是代码中有几处的写法我不是很理解,希望Dr zhang能够多多指教。先谢谢了。
-
首先,在博客中提到的NN输入层的次元数是(n_models, batch_size, n_steps, n_input)
(in this case, the input layer handles four dimensions: (n_models, batch_size, n_steps, n_input)
). 但是在实际代码中定义的输入层的次元却是(n_models, n_steps, batch_size, n_input)
(line 167
). 可以看到n_steps
和batch_size
位置调换了,这是一个手误还是故意这么安排的?我觉得batch_size在前的话貌似更好理解一些。
-
在全连接层的权重与偏置运算中(line 105-113
),定义outpot这个field的意思是什么?如果只是单纯的线性运算的话,那么hidden层和output层的次元应该是相同的不是吗?如果按照初始化NN的设置(line 159-160),hidden层与output层的次元不同,那么如果在debug模式下,line 110
是会报溢出的错误的。非debug模式下是可以运行的,但是这样的话忽略了hidden层溢出的部分,这样做没问题吗?
-
与2同样的问题,如line 249
所示,target_centers
是一个VectorField,次元为(BATCH_SIZE, 3)。但是在line 553
处从训练数据中读取target_centers
时,在debug模式下当迭代到第二个batch时target_centers
会溢出。同样的问题,也在之后的fill_input_states
函数中出现。
-
在line 211中定义test_data
,但是并没有使用它。如果要使用test_data
来验证训练模型模型的话该怎么考虑呢?
虽然太极在非debug模式下是可以溢出访问field的,但是这样超过事先定义好的field的次元的话是没问题的吗?或者说会有什么隐藏问题。以上,主要是关于NN定义与训练的部分,个人对于太极的使用还不是很熟练,还请多多赐教。关于模拟的部分,由于我之间没有接触过sph模型,现在还在学习当中。
Hi @C.Ying , 欢迎来到taichi社区。
感谢关注到这篇博客,关于其中的问题:
- 这个是确实是博客里写的内容和代码实现上有一些出入,把
batch_size
提前的话也没有问题
- 这个
output
是因为从hidden
出来后可能会过一个非线性激活函数,这里确实应该是把hidden
和output
的大小定义一致的,good catch。
- 关于越界的问题,在非debug模式下,对于超出定义维度的index,会被做一个对数组长度的取模操作,但不推荐借用这个特性,还是推荐用debug模式验证是否越界。
- 这里的test data是相对于training data来说的unseen data,用来验证模型的训练效果的
谢谢Dr zhang的及时回复。我大体上明白了这四点问题。
另外,如果按照源代码中设置的默认参数来训练NN控制器,其控制效果和博客中展示的有很大出入。
如下图所示,上边用的是github上公开的pretrained模型,下边是使用默认参数训练出来的模型。
可以看到使用默认参数训练出来的模型效果不好。因此,我想问的是pretrained模型在怎么训练出来的呢?是否有哪些tricks可以分享一下?(比如,batch size,train data number,weight/bias shape and learning rate etc.)
再次感谢。
(pretrained)
continued
(trained on default parameters)
C.Ying
#5
06/20 追记 @mzhang
在1.2.0版本之后,taichi增加了break auto-diff rule validation 功能。
如果开启这个检查之后,现在版本的diff-sph代码将会报错。
具体是在482-483行和486-487行:
for j in ti.static(range(3)):
if F_pos[bs, t, i][j] < boundary_box[0][j]:
F_pos[bs, t, i][j] = boundary_box[0][j]
collision_normal[j] += -1.0
for j in ti.static(range(3)):
if F_pos[bs, t, i][j] > boundary_box[1][j]:
F_pos[bs, t, i][j] = boundary_box[1][j]
collision_normal[j] += 1.0
这里的两个判断语句需要先读取F_pos[bs, t, i][j]
的值,再写入到F_pos[bs, t, i][j]
。
这违反了taichi中的auto-diff的规则(不能先读取再写入)。从而使得求出的grad是不正确的。(如果打印 weight.grad/bias.grad,会发现grad的量级在10^2~10^3。)
因此,如上面的问题一样,pretrained.pkl模型是怎么训练出来的?diff-sph有发布新的版本吗?