33
44#include <string.h>
55
6+ #include "eml_linreg.c"
7+
68// memset/memcpy for compatibility
79#if !defined(__linux__ )
810void * memcpy (void * dst , const void * src , size_t n ) {
@@ -13,102 +15,6 @@ void *memset(void *s, int c, size_t n) {
1315}
1416#endif
1517
16- #include <math.h>
17-
18- // ElasticNet implementation (embedded from linreg.c)
19- typedef struct {
20- float * weights ;
21- float * weight_gradients ;
22- float bias ;
23- uint16_t n_features ;
24- float l1_ratio ;
25- float alpha ;
26- float learning_rate ;
27- } elastic_net_model_t ;
28-
29- // Soft thresholding function for L1 penalty
30- static float soft_threshold (float x , float threshold ) {
31- if (x > threshold ) {
32- return x - threshold ;
33- } else if (x < - threshold ) {
34- return x + threshold ;
35- } else {
36- return 0.0f ;
37- }
38- }
39-
40- // Calculate prediction for a single sample
41- static float predict_sample (const elastic_net_model_t * model , const float * features ) {
42- float prediction = model -> bias ;
43- for (uint16_t i = 0 ; i < model -> n_features ; i ++ ) {
44- prediction += model -> weights [i ] * features [i ];
45- }
46- return prediction ;
47- }
48-
49- // Single iteration of gradient descent
50- static void elastic_net_iterate (elastic_net_model_t * model ,
51- const float * X ,
52- const float * y ,
53- uint16_t n_samples ) {
54-
55- // Initialize gradients buffer to zero
56- memset (model -> weight_gradients , 0 , model -> n_features * sizeof (float ));
57- float bias_gradient = 0.0f ;
58-
59- // Forward pass and gradient calculation
60- for (uint16_t i = 0 ; i < n_samples ; i ++ ) {
61- // Calculate prediction
62- float prediction = predict_sample (model , & X [i * model -> n_features ]);
63-
64- // Calculate error
65- float error = prediction - y [i ];
66-
67- // Accumulate gradients
68- bias_gradient += error ;
69- for (uint16_t j = 0 ; j < model -> n_features ; j ++ ) {
70- model -> weight_gradients [j ] += error * X [i * model -> n_features + j ];
71- }
72- }
73-
74- // Average gradients
75- bias_gradient /= n_samples ;
76- for (uint16_t j = 0 ; j < model -> n_features ; j ++ ) {
77- model -> weight_gradients [j ] /= n_samples ;
78- }
79-
80- // Update weights with regularization
81- for (uint16_t j = 0 ; j < model -> n_features ; j ++ ) {
82- // Add L2 penalty to gradient
83- float l2_penalty = model -> alpha * (1.0f - model -> l1_ratio ) * model -> weights [j ];
84-
85- // Update weight
86- float new_weight = model -> weights [j ] - model -> learning_rate * (model -> weight_gradients [j ] + l2_penalty );
87-
88- // Apply L1 penalty via soft thresholding
89- float l1_penalty = model -> alpha * model -> l1_ratio * model -> learning_rate ;
90- model -> weights [j ] = soft_threshold (new_weight , l1_penalty );
91- }
92-
93- // Update bias (no regularization on bias)
94- model -> bias -= model -> learning_rate * bias_gradient ;
95- }
96-
97- // Calculate mean squared error
98- static float elastic_net_mse (const elastic_net_model_t * model ,
99- const float * X ,
100- const float * y ,
101- uint16_t n_samples ) {
102-
103- float mse = 0.0f ;
104- for (uint16_t i = 0 ; i < n_samples ; i ++ ) {
105- float prediction = predict_sample (model , & X [i * model -> n_features ]);
106- float error = y [i ] - prediction ;
107- mse += error * error ;
108- }
109- return mse / n_samples ;
110- }
111-
11218// MicroPython type for ElasticNet model
11319typedef struct _mp_obj_elasticnet_model_t {
11420 mp_obj_base_t base ;
0 commit comments