@@ -4,60 +4,59 @@ defmodule LearnKit.Regression.Linear.Calculations do
44 """
55
66 alias LearnKit.Math
7+ alias LearnKit.Regression.Linear
78
89 defmacro __using__ ( _opts ) do
910 quote do
10- defp do_fit ( method , factors , results ) when method == "gradient descent" do
11- gradient_descent_iteration ( [ :rand . uniform , :rand . uniform ] , 0.0001 , nil , 1000000 , Enum . zip ( factors , results ) , 0 )
11+ defp do_fit ( method , % Linear { factors: factors , results: results } )
12+ when method == "gradient descent" do
13+ gradient_descent_iteration (
14+ [ :rand . uniform ( ) , :rand . uniform ( ) ] ,
15+ 0.0001 ,
16+ nil ,
17+ 1_000_000 ,
18+ Enum . zip ( factors , results ) ,
19+ 0
20+ )
1221 end
1322
14- defp do_fit ( _ , factors , results ) do
15- beta = Math . correlation ( factors , results ) * Math . standard_deviation ( results ) / Math . standard_deviation ( factors )
23+ defp do_fit ( _ , % Linear { factors: factors , results: results } ) do
24+ beta =
25+ Math . correlation ( factors , results ) * Math . standard_deviation ( results ) /
26+ Math . standard_deviation ( factors )
27+
1628 alpha = Math . mean ( results ) - beta * Math . mean ( factors )
1729 [ alpha , beta ]
1830 end
1931
20- defp predict_sample ( sample , [ alpha , beta ] ) do
21- sample * beta + alpha
32+ defp do_predict ( linear , samples ) do
33+ Enum . map ( samples , fn sample ->
34+ { :ok , prediction } = predict ( linear , sample )
35+ prediction
36+ end )
2237 end
2338
24- defp calculate_score ( [ ] , _ , _ ) , do: raise ( "There was no fit for model" )
25-
26- defp calculate_score ( coefficients , factors , results ) do
27- 1.0 - sum_of_squared_errors ( coefficients , factors , results ) / total_sum_of_squares ( results )
28- end
29-
30- defp total_sum_of_squares ( list ) do
31- mean_list = Math . mean ( list )
32- Enum . reduce ( list , 0 , fn x , acc -> acc + :math . pow ( x - mean_list , 2 ) end )
33- end
34-
35- defp sum_of_squared_errors ( coefficients , factors , results ) do
36- Enum . zip ( factors , results )
37- |> Enum . reduce ( 0 , fn { xi , yi } , acc -> acc + squared_prediction_error ( coefficients , xi , yi ) end )
38- end
39-
40- defp squared_prediction_error ( coefficients , x , y ) do
41- coefficients
42- |> prediction_error ( x , y )
43- |> :math . pow ( 2 )
44- end
39+ defp squared_error_gradient ( linear , x , y ) do
40+ error_variable = prediction_error ( linear , x , y )
4541
46- defp squared_error_gradient ( coefficients , x , y ) do
47- error_variable = prediction_error ( coefficients , x , y )
4842 [
4943 - 2 * error_variable ,
5044 - 2 * error_variable * x
5145 ]
5246 end
5347
54- defp prediction_error ( coefficients , x , y ) do
55- y - predict_sample ( x , coefficients )
56- end
57-
58- defp gradient_descent_iteration ( _ , _ , min_theta , _ , _ , iterations_with_no_improvement ) when iterations_with_no_improvement >= 100 , do: min_theta
59-
60- defp gradient_descent_iteration ( theta , alpha , min_theta , min_value , data , iterations_with_no_improvement ) do
48+ defp gradient_descent_iteration ( _ , _ , min_theta , _ , _ , iterations_with_no_improvement )
49+ when iterations_with_no_improvement >= 100 ,
50+ do: min_theta
51+
52+ defp gradient_descent_iteration (
53+ theta ,
54+ alpha ,
55+ min_theta ,
56+ min_value ,
57+ data ,
58+ iterations_with_no_improvement
59+ ) do
6160 [
6261 min_theta ,
6362 min_value ,
@@ -69,14 +68,26 @@ defmodule LearnKit.Regression.Linear.Calculations do
6968 data
7069 |> Enum . shuffle ( )
7170 |> Enum . reduce ( theta , fn { xi , yi } , acc ->
72- gradient_i = squared_error_gradient ( acc , xi , yi )
71+ gradient_i = squared_error_gradient ( % Linear { coefficients: theta } , xi , yi )
7372 acc |> Math . vector_subtraction ( alpha |> Math . scalar_multiply ( gradient_i ) )
7473 end )
75- gradient_descent_iteration ( theta , alpha , min_theta , min_value , data , iterations_with_no_improvement )
74+
75+ gradient_descent_iteration (
76+ theta ,
77+ alpha ,
78+ min_theta ,
79+ min_value ,
80+ data ,
81+ iterations_with_no_improvement
82+ )
7683 end
7784
7885 defp check_value ( data , min_value , theta , min_theta , iterations_with_no_improvement , alpha ) do
79- value = Enum . reduce ( data , 0 , fn { xi , yi } , acc -> acc + squared_prediction_error ( theta , xi , yi ) end )
86+ value =
87+ Enum . reduce ( data , 0 , fn { xi , yi } , acc ->
88+ acc + squared_prediction_error ( % Linear { coefficients: theta } , xi , yi )
89+ end )
90+
8091 cond do
8192 value < min_value ->
8293 [ theta , value , 0 , 0.0001 ]
0 commit comments