Wolfram Function Repository
Instant-use add-on functions for the Wolfram Language
Function Repository Resource:
Create a NetGraph with a simplified rule-based interface
| ResourceFunction["RuleNetGraph"][layer1→layer2→…→layern] creates a NetGraph object from the specified layers. | |
 as a hot-key to enter a subscript.
 as a hot-key to enter a subscript.Build a simple NetGraph using a list of rules:
| In[1]:= | ![ResourceFunction["RuleNetGraph"][LogisticSigmoid -> (#*17 + 8 &)]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/1a9b50ad2227b4e1.png) | 

Use lists of NetPort objects and layers for more complicated networks:
| In[2]:= | ![ResourceFunction["RuleNetGraph"][{NetPort["Input1"], NetPort["Input2"]}
  -> {Plus, Times} -> CatenateLayer[] -> LinearLayer[3] -> SoftmaxLayer[]]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/3441e3e413ebea60.png) | 

Use string subscripts to manually specify layer names:
| In[3]:= | ![ResourceFunction["RuleNetGraph"][{
   
\!\(\*SubscriptBox[\(LinearLayer[32]\), \("\<lin32\>"\)]\) -> 
\!\(\*SubscriptBox[\(LinearLayer[64]\), \("\<lin64\>"\)]\),
   "lin32"
   } -> 
\!\(\*SubscriptBox[\(CatenateLayer[]\), \("\<cat\>"\)]\) -> Ramp -> 
\!\(\*SubscriptBox[\(LinearLayer[3]\), \("\<logits\>"\)]\) -> 
\!\(\*SubscriptBox[\(SoftmaxLayer[]\), \("\<pred\>"\)]\) ]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/459b0d35495969a7.png) | 
| Out[3]= |  | 
| In[4]:= | ![ResourceFunction["RuleNetGraph"][NetPort["Input"] -> 
\!\(\*SubscriptBox[\(ElementwiseLayer["\<Sigmoid\>"]\), \("\<MySigmoid\>"\)]\)]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/448b567e674ae0d4.png) | 
| Out[4]= |  | 
The above is equivalent to:
| In[5]:= | ![ResourceFunction["RuleNetGraph"][NetPort["Input"] ->
  Subscript[ElementwiseLayer["Sigmoid"], "MySigmoid"]]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/71bab812779c3d54.png) | 

And is also equivalent to:
| In[6]:= | ![NetGraph[<|"MySigmoid" -> ElementwiseLayer["Sigmoid"]|>,
 {NetPort["Input"] -> "MySigmoid"}]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/6d2c92ab116339d4.png) | 

A list of rules can be used to specify network connections in any order:
| In[7]:= | ![ResourceFunction["RuleNetGraph"][{
  {"act1", "act2"} -> Times,
  NetPort["Input1"] -> 
\!\(\*SubscriptBox[\(ElementwiseLayer["\<Sigmoid\>"]\), \("\<act1\>"\)]\),
  NetPort["Input1"] -> 
\!\(\*SubscriptBox[\(SoftmaxLayer[]\), \("\<act2\>"\)]\)
  }]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/1e450ee31cf52fbd.png) | 
| Out[7]= |  | 
Networks can be specified with multiple inputs and outputs:
| In[8]:= | ![ResourceFunction["RuleNetGraph"][{
  {NetPort["Sin"] -> 
\!\(\*SubscriptBox[\((#^2 &)\), \("\<s^2\>"\)]\), NetPort["Cos"] -> 
\!\(\*SubscriptBox[\((#^2 &)\), \("\<c^2\>"\)]\)} -> Plus -> NetPort["Sum"],
  {NetPort["Cos"], NetPort["Sin"]} -> ThreadingLayer[(ArcTan[#cos, #sin] &)] -> NetPort["Angle"]
  }]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/1e372086c582e9e8.png) | 
| Out[8]= |  | 
Additional arguments are passed through RuleNetGraph to NetGraph (for example, input port size):
| In[9]:= | ![ResourceFunction["RuleNetGraph"][NetPort["Input"] -> ConvolutionLayer[32, 3, "Stride" -> 2 , "PaddingSize" -> 1]
   -> BatchNormalizationLayer[]
    -> Ramp, "Input" -> {3, 32, 32}]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/034f8e51bb746faa.png) | 

RuleNetGraph can easily describe networks with complicated data flow:
| In[10]:= | ![denseBnRelu[n_Integer] := NetChain[{
   LinearLayer@n, BatchNormalizationLayer[], Ramp}]
ResourceFunction["RuleNetGraph"][{{
    {
      
\!\(\*SubscriptBox[\(denseBnRelu[64]\), \("\<dense1\>"\)]\),
      
\!\(\*SubscriptBox[\(denseBnRelu[64]\), \("\<dense2\>"\)]\),
      denseBnRelu[128] -> denseBnRelu[64],
      denseBnRelu[128] -> denseBnRelu[64],
      NetPort["MidAdjust"]
      } -> 
\!\(\*SubscriptBox[\(Plus\), \("\<FirstPlus\>"\)]\) -> {denseBnRelu[
        64], denseBnRelu[64]},
    "dense1",
    "dense2",
    NetPort["OutAdjust"],
    "FirstPlus" -> 
\!\(\*SubscriptBox[\((\((#^2)\)/2 &)\), \("\<x^2/2\>"\)]\)} -> Plus -> 
\!\(\*SubscriptBox[\(LinearLayer[12]\), \("\<logits\>"\)]\) ->
     
\!\(\*SubscriptBox[\(SoftmaxLayer[]\), \("\<pred\>"\)]\)}]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/514b0bd9e0875bc0.png) | 
| Out[11]= |  | 
Multiple layers cannot be declared with the same manually-assigned name:
| In[12]:= | ![ResourceFunction["RuleNetGraph"][NetPort["Input"] -> 
\!\(\*SubscriptBox[\(LogisticSigmoid\), \("\<MyActivation\>"\)]\) -> 
\!\(\*SubscriptBox[\((#*17 + 8 &)\), \("\<MyActivation\>"\)]\)]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/0f15393bfb53e907.png) | 
| Out[12]= |  | 
You cannot reuse layers in a way that causes the output of a layer to depend on itself:
| In[13]:= | ![ResourceFunction["RuleNetGraph"][NetPort["Input"] -> 
\!\(\*SubscriptBox[\(LogisticSigmoid\), \("\<MyActivation\>"\)]\) -> "MyActivation"]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/7fb7e0d37f5d9de7.png) | 
| Out[13]= |  | 
Manual layer names must be specified with a string subscript; non-strings prompt a message:
| In[14]:= | ![ResourceFunction["RuleNetGraph"][
 NetPort["Input"] -> Subscript[LogisticSigmoid, MyActivation]]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/70b5b33b3883c08c.png) | 
| Out[14]= |  | 
| In[15]:= | ![ResourceFunction["RuleNetGraph"][NetPort["Input"] -> 
\!\(\*SubscriptBox[\(LogisticSigmoid\), \("\<MyActivation\>"\)]\)]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/0d71c95bb04efb78.png) | 
| Out[15]= |  | 
All layers must be properly declared:
| In[16]:= | ![ResourceFunction["RuleNetGraph"][NetPort["Input"] -> SoftmaxLayer]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/52a774a7473e5169.png) | 
| Out[16]= |  | 
Calling the layer with zero arguments works:
| In[17]:= | ![ResourceFunction["RuleNetGraph"][NetPort["Input"] -> SoftmaxLayer[]]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/4d8ecb8adb3ad195.png) | 
| Out[17]= |  | 
The first argument of RuleNetGraph must contain at least one Rule ( →):
| In[18]:= | ![ResourceFunction["RuleNetGraph"][SoftmaxLayer[]]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/7c2398e1972432ff.png) | 
| Out[18]= |  | 
| In[19]:= | ![ResourceFunction["RuleNetGraph"][NetPort["Input"] -> SoftmaxLayer[]]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/11a2271a819f0336.png) | 
| Out[19]= |  | 
You cannot use string subscripts on NetPort or any other parameter that is not a manually named layer:
| In[20]:= | ![ResourceFunction["RuleNetGraph"][
\!\(\*SubscriptBox[\(NetPort["\<Input1\>"]\), \("\<1\>"\)]\) -> SoftmaxLayer[]]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/3ac813c69df0fcf1.png) | 
| Out[20]= |  | 
You will get errors if you try to use a function that cannot be automatically converted to a neural network layer:
| In[21]:= | ![ResourceFunction["RuleNetGraph"][
 NetPort["Input1"] -> (Transpose[#, {3, 2, 1}] &)]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/29b3e150131a0340.png) | 
| Out[21]= |  | 
| In[22]:= | ![ResourceFunction["RuleNetGraph"][
 NetPort["Input1"] -> TransposeLayer[{3, 2, 1}]]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/02c87a8eba5aa894.png) | 
| Out[22]= |  | 
Be careful to properly group symbols. This gives an error:
| In[23]:= | ![ResourceFunction["RuleNetGraph"][NetPort["Input1"] -> #*4 &]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/529083acec23ce49.png) | 
| Out[23]= |  | 
Giving the pure function proper precedence with parentheses fixes it:
| In[24]:= | ![ResourceFunction["RuleNetGraph"][NetPort["Input1"] -> (#*4 &)]](https://www.wolframcloud.com/obj/resourcesystem/images/de6/de65c6dc-c7e5-478e-9c81-48e04a0072aa/3c5456af876afb31.png) | 
| Out[24]= |  | 
This work is licensed under a Creative Commons Attribution 4.0 International License