001 (ns org.clojars.punit-naik.clj-ml.linear-regression
002 (:require [org.clojars.punit-naik.clj-ml.utils.matrix :as matrix]))
003
004 (defn generate-input-matrix
005 "Receives a data matrix like [[x-1a x-1b x-1c...x-1z y-1]... [x-na x-nb x-nc...x-nz y-n]] with features and outputs
006 And generates an input matrix like [[1 x-1a x-1b x-1c...x-1z]... [1 x-na x-nb x-nc...x-nz]]"
007 [data]
008 (map (comp (partial cons 1) drop-last) data))
009
010 (defn generate-output-matrix
011 "Receives a data matrix like [[x-1a x-1b x-1c...x-1z y-1]... [x-na x-nb x-nc...x-nz y-n]] with features and outputs
012 And generates an output matrix like [[y-1]... [y-n]]"
013 [data]
014 (map (comp list last) data))
015
016 (defmulti betas
017 "Receives a dispath value `method` and data matrix like [[x-1a x-1b x-1c...x-1z y-1]... [x-na x-nb x-nc...x-nz y-n]] with features and outputs
018 And generates betas list like [b-0 b-a..b-z] using linear regression which can be used to predict output for any input [x-a...x-z]
019 Like Y = b-0 * 1 + b-a * x-a + .... + b-z * x-z"
020 (fn [method _]
021 method))
022
023 (defmethod betas :matrix
024 [_ data]
025 (let [input-matrix (generate-input-matrix data)
026 input-matrix-transposed (matrix/transpose input-matrix)
027 output-matrix (generate-output-matrix data)
028 input-matrix-transposed-multiplied-by-input-matrix (matrix/matrix-multiply input-matrix-transposed input-matrix)
029 input-matrix-transposed-multiplied-by-output-matrix (matrix/matrix-multiply input-matrix-transposed output-matrix)
030 input-matrix-transposed-multiplied-by-input-matrix-inverse (matrix/inverse input-matrix-transposed-multiplied-by-input-matrix)]
031 (map first (matrix/matrix-multiply input-matrix-transposed-multiplied-by-input-matrix-inverse input-matrix-transposed-multiplied-by-output-matrix))))
032
033 (defn predict
034 "Predicts output value for a set of features [x-a...x-z]
035 Given the beta values [b-0 b-a...b-z] for the training data"
036 [betas inputs]
037 (->> (cons 1 inputs)
038 (map * betas)
039 (reduce +)))