| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| #= |
| This script shows how a simple MLP net may be used |
| for regression. It shows how data in memory may be |
| used for training and evaluation, and how to obtain |
| the predictions from the trained net. |
| =# |
| using MXNet |
| using Distributions |
| #using Plots |
| |
| # data generating process |
| generate_inputs(mean, var, size) = rand(MvNormal(mean, var), size) |
| output(data) = sin.(data[1:1,:]).*sin.(data[2:2,:])./(data[1:1,:].*data[2:2,:]) |
| |
| # create training and evaluation data sets |
| mean=[0.0; 0.0] |
| var=[1.0 0.0; 0.0 1.0] |
| samplesize = 5000 |
| TrainInput = generate_inputs(mean, var, samplesize) |
| TrainOutput = output(TrainInput) |
| ValidationInput = generate_inputs(mean, var, samplesize) |
| ValidationOutput = output(ValidationInput) |
| |
| # how to set up data providers using data in memory |
| function data_source(batchsize = 100) |
| train = mx.ArrayDataProvider( |
| :data => TrainInput, |
| :label => TrainOutput, |
| batch_size = batchsize, |
| shuffle = true, |
| ) |
| valid = mx.ArrayDataProvider( |
| :data => ValidationInput, |
| :label => ValidationOutput, |
| batch_size = batchsize, |
| shuffle = true, |
| ) |
| |
| train, valid |
| end |
| |
| # create a two hidden layer MPL: try varying num_hidden, and change tanh to relu, |
| # or add/remove a layer |
| data = mx.Variable(:data) |
| label = mx.Variable(:label) |
| net = @mx.chain mx.Variable(:data) => |
| mx.FullyConnected(num_hidden=10) => |
| mx.Activation(act_type=:tanh) => |
| mx.FullyConnected(num_hidden=3) => |
| mx.Activation(act_type=:tanh) => |
| mx.FullyConnected(num_hidden=1) => |
| mx.LinearRegressionOutput(mx.Variable(:label)) |
| |
| # final model definition, don't change, except if using gpu |
| model = mx.FeedForward(net, context=mx.cpu()) |
| |
| # set up the optimizer: select one, explore parameters, if desired |
| #optimizer = mx.SGD(η=0.01, μ=0.9, λ=0.00001) |
| optimizer = mx.ADAM() |
| |
| # train, reporting loss for training and evaluation sets |
| # initial training with small batch size, to get to a good neighborhood |
| trainprovider, evalprovider = data_source(#= batchsize =# 200) |
| mx.fit(model, optimizer, trainprovider, |
| initializer = mx.NormalInitializer(0.0, 0.1), |
| eval_metric = mx.MSE(), |
| eval_data = evalprovider, |
| n_epoch = 20, |
| callbacks = [mx.speedometer()]) |
| # more training with the full sample |
| trainprovider, evalprovider = data_source(#= batchsize =# samplesize) |
| mx.fit(model, optimizer, trainprovider, |
| initializer = mx.NormalInitializer(0.0, 0.1), |
| eval_metric = mx.MSE(), |
| eval_data = evalprovider, |
| n_epoch = 500, # previous setting is batchsize = 200, epoch = 20 |
| # implies we did (5000 / 200) * 20 times update in previous `fit` |
| callbacks = [mx.speedometer()]) |
| |
| # obtain predictions |
| plotprovider = mx.ArrayDataProvider(:data => ValidationInput, :label => ValidationOutput) |
| fit = mx.predict(model, plotprovider) |
| println("correlation between fitted values and true regression line: ", cor(vec(fit), vec(ValidationOutput))) |
| #scatter(ValidationOutput',fit',w = 3, xlabel="true", ylabel="predicted", title="45º line is what we hope for", show=true) |