MLP on housing data

This example replicates the housing data example from the Knet.jl readme. Although wecould have reused more of Flux (see the mnist example), the library’s abstractions are very lightweight and don’t force you into any particular strategy.

Load the necessary packages.

using Flux, Statistics, DelimitedFiles
using Flux: Params, gradient
using Flux.Optimise: update!
using DelimitedFiles, Statistics
using Parameters: @with_kw


Struct to define hyperparameters.

@with_kw mutable struct Hyperparams
    lr::Float64 = 0.1		# learning rate
    split_ratio::Float64 = 0.1	# Train Test split ratio, define percentage of data to be used as Test data
end


Define the function that donwloads the housing data.

function get_processed_data(args)

    isfile("housing.data") ||
        download("https://raw.githubusercontent.com/MikeInnes/notebooks/master/housing.data",
            "housing.data")

    rawdata = readdlm("housing.data")'

    # The last feature is our target -- the price of the house.
    split_ratio = args.split_ratio # For the train test split

    x = rawdata[1:13,:]
    y = rawdata[14:14,:]

    # Normalise the data
    x = (x .- mean(x, dims = 2)) ./ std(x, dims = 2)

    # Split into train and test sets
    split_index = floor(Int,size(x,2)*split_ratio)
    x_train = x[:,1:split_index]
    y_train = y[:,1:split_index]
    x_test = x[:,split_index+1:size(x,2)]
    y_test = y[:,split_index+1:size(x,2)]

    train_data = (x_train, y_train)
    test_data = (x_test, y_test)

    return train_data,test_data
end


Set struct to define model.

mutable struct model
    W::AbstractArray
    b::AbstractVector
end


Function to predict output from given parameters

predict(x, m) = m.W*x .+ m.b


Set Mean Squared Error as the loss function.

meansquarederror(, y) = sum(( .- y).^2)/size(y, 2)


Define the train function.

function train(; kws...)
    # Initialize the Hyperparamters
    args = Hyperparams(; kws...)
    
    # Load the data
    (x_train,y_train),(x_test,y_test) = get_processed_data(args)
    
    # The model
    m = model((randn(1,13)),[0.])
    
    loss(x, y) = meansquarederror(predict(x, m), y)

    ## Training
    η = args.lr
    θ = params([m.W, m.b])

    for i = 1:500
      g = gradient(() -> loss(x_train, y_train), θ)
      for x in θ
        update!(x, -g[x]*η)
      end
      if i%100==0
          @show loss(x_train, y_train)
        end
    end
    
    # Predict the RMSE on the test set
    err = meansquarederror(predict(x_test, m),y_test)
    println(err)
end


Finally, train the model.

cd(@__DIR__)
train()


Output:

loss(x_train, y_train) = 1.5581866732347647e48
loss(x_train, y_train) = 5.346256832813508e93
loss(x_train, y_train) = 1.8343413285051722e139
loss(x_train, y_train) = 6.293764431237339e184
loss(x_train, y_train) = 2.1594383826148733e230
1.7081066852828434e230

– Adarsh Kumar, Mike J Innes, Shreyas Kowshik, Hongkee Yoon