In the recent new in Mathematica 11 webinar one user asked during the Q&A session wether the current implementation of neural networks in Mathematica 11 could be used for processing time series. As far as I remember Taliesin Beynon answer was something along the line of
Recurrent Neural Networks will eventually come to Mathematica in a later version. Until then one could use a Convolutional Neural Network on a time series as if it were an image and "fake" the extra dimensions
I'd like to do exactly that but am unsure how to proceed. Take for an (somewhat silly) example stock prices of various companies from either tech or financial industry from 2007 to now. One interesting question might be wether a network can be trained to discern which industry a company belongs to based on its stock's course over the years (including the 2008/2009 financial crisis). The stocks I am looking at are
tech = {"GE", "AAPL", "MSFT", "MRK", "IBM"};
banks = {"DB", "C", "BAC", "HSBC", "BCS"};
A display of the stock prices (resized to values between 0 and 1) can be generated with
Callout[FinancialData[#, "Jan. 1, 2007"] //
Replace[Transpose@#, {a_, b_} :>
Transpose@{a, Rescale@b} ] &, #] & /@ tech // DateListPlot
Callout[FinancialData[#, "Jan. 1, 2007"] //
Replace[Transpose@#, {a_, b_} :>
Transpose@{a, Rescale@b} ] &, #] & /@ banks // DateListPlot
For the network I'd like to use 100 input nodes (corresponds to a $1\times 100$ or $100\times 1$ pixel image). The following function gives a downsampled version of a stock course with 100 data points and stock prices rescaled to values between 0 and 1.
financialDataToList[stock_] :=
FinancialData[stock, "Jan. 1, 2007"] // Transpose // Last //
Rescale // ArrayResample[#, 100] &
For visualization ArrayPlot
can be used
myarrayplot[stock_] :=
{financialDataToList@stock // List //ArrayPlot[#, AspectRatio -> 1/4] &, stock}
Grid[#, Alignment -> Left] & @*Map[myarrayplot] /@ {tech, banks} //
List // Grid[#, Spacings -> {5, 1}] &
The following function gives the stock price time series as an image (note that ArrayPlot
and Image
transform numbers to grayscale differently; to get the same visualization one has to invert black and white (via a :> (1-a)
)
toImage[stock_] := financialDataToList@stock //List //Replace[#, a_ :> (1 - a)] & //Image
The net I'd to use may look like this (one or more convolutions/poolings followed by a fully connected layer and outputs that indicate the likelihood of belonging to the respective branch of industry). Feel free to make any sensible adjustments.
net = NetChain[{
ConvolutionLayer[5, {1, 20}],
PoolingLayer[{1, 5}, "Stride" -> {4, 4}],
FlattenLayer[],
DotPlusLayer[2]},
"Input" -> NetEncoder[{"Image", {100, 1}, "Grayscale"}],
"Output" -> NetDecoder[{"Class", {"tech", "banks"}}]]
The training data can be generated with
trainingdata = Join[
Thread[(toImage /@ tech) -> "tech" ],
Thread[(toImage /@ banks) -> "banks"] ]
Calling NetTrain[net, trainingdata]
does result in an error I suspect is a direct cause of me not really knowing how to correctly specify the dimensions of input, output and the layers. I am not that familiar with neural networks in practice but have a general understanding of how the individual layers work in principle. Sadly the documentation is lacking of more full examples showing how to connect individual layers to form a working/useful net.
EmbeddingLayer
cannot be connected toConvolutionLayer
. I would like to replicate this: github.com/fchollet/keras/blob/master/examples/imdb_cnn.py $\endgroup$NetSequenceEncoder[{"Text", <alphabet>}]
, and then you'll be able to feed strings into the net, they'll get encoded as sequences of integers, those will get embedded, and you can convolve them. But frankly, the embedding layer is redundant, it's equivalent to using one hot embedding and letting the convolution learn the basis. $\endgroup$