11
$\begingroup$

I think I understand how to create a neural net that has multiple categorical inputs, but I don't seem to be able to invoke NetTrain successfully on it.

As a concrete example, suppose the data I want to train against maps two categorical inputs, each drawn from classes {a, b, c}, to a numerical tensor with dimensions {2}.

Some data looks like this:

In[1]:= data = 
 Table[<|"Input1" -> RandomChoice[{a, b, c}], 
    "Input2" -> RandomChoice[{a, b, c}]|> -> RandomReal[1, 2], 10]

Out[1]= {<|"Input1" -> b, "Input2" -> a|> -> {0.833467, 0.928599}, 
         <|"Input1" -> a, "Input2" -> c|> -> {0.984507, 0.38375},
         <|"Input1" -> c, "Input2" -> a|> -> {0.0477534, 0.750165},
         <|"Input1" -> a, "Input2" -> a|> -> {0.641454, 0.55485},
         <|"Input1" -> c, "Input2" -> a|> -> {0.854673, 0.0175461}, 
         <|"Input1" -> c, "Input2" -> b|> -> {0.518462, 0.00939247}, 
         <|"Input1" -> c, "Input2" -> c|> -> {0.323348, 0.993629}, 
         <|"Input1" -> c, "Input2" -> c|> -> {0.757127, 0.185508}, 
         <|"Input1" -> b, "Input2" -> b|> -> {0.634778, 0.127342}, 
         <|"Input1" -> c, "Input2" -> a|> -> {0.173669, 0.0696255}}

I expected the following neutral net to be compatible with this data:

In[2]:= net = 
 NetGraph[{CatenateLayer[], 2},
   {{NetPort["Input1"], NetPort["Input2"]} -> 1, 
    1 -> 2 -> NetPort["Output1"]}, 
  "Input1" -> {"Class", {a, b, c}, "UnitVector"}, 
  "Input2" -> {"Class", {a, b, c}, "UnitVector"}]

Out[2]=

Neutral net with multiple categorical inputs

And at first it seems to work:

In[3]:= NetInitialize[net][<|"Input1" -> a, "Input2" -> c|>]

Out[3]= {-0.186007, -0.193141}

But NetTrain fails:

In[4]:= NetTrain[net, data]

Out[4]= ("Input spec cannot be used with the given net.")

Any ideas what is happening here? Am I use CatenateLayer correctly?

$\endgroup$
11
$\begingroup$
  1. format of data is incorrect, you should make separate key for output
  2. you forgot about NetEncoder for inputs
data = Table[
   <|
    "Input1" -> RandomChoice[{a, b, c}],
    "Input2" -> RandomChoice[{a, b, c}],
    "Output" -> RandomReal[1, 2]
    |>
   ,
   10
   ];

net = NetGraph[
  {
   CatenateLayer[],
   2
   },
  {
   NetPort["Input1"] -> 1,
   NetPort["Input2"] -> 1,
   1 -> 2
   },
  "Input1" -> NetEncoder[{"Class", {a, b, c}, "UnitVector"}],
  "Input2" -> NetEncoder[{"Class", {a, b, c}, "UnitVector"}],
  "Output" -> 2
  ]

net = NetTrain[net, data]
$\endgroup$
  • 1
    $\begingroup$ Cool, this does work. Any insight into why the NetEncoder for inputs is required? I got the impression from the docs that it is implicit with "Input1" -> {"Class", etc}. $\endgroup$ – Andrew Moylan Sep 18 '16 at 10:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.