@@ -560,37 +560,25 @@ model = PySRRegressor(
560560model.fit(X, y)
561561```
562562
563- You can also use parameters in your template expressions, which will be optimized during the search:
564-
565- ``` python
566- template = TemplateExpressionSpec(
567- expressions = [" f" , " g" ],
568- variable_names = [" x1" , " x2" , " x3" ],
569- parameters = {" p1" : 2 , " p2" : 1 }, # p1 has length 2, p2 has length 1
570- combine = " p1[1] * sin(f(x1, x2)) + p1[2] * g(x3) + p2[1]" ,
571- )
572- ```
573-
574- This will learn an equation of the form:
575-
576- $$ y = \alpha_1 \sin(f(x_1, x_2)) + \alpha_2 g(x_3) + \beta $$
577-
578- where $\alpha_1, \alpha_2$ are stored in ` p1 ` and $\beta$ is stored in ` p2 ` . The parameters will be optimized during the search.
579-
580563### Parametric Expressions
581564
582565When your data has categories with shared equation structure but different parameters,
583- you can use a ` ParametricExpressionSpec ` . Let's say we would like to learn the expression:
566+ you can use the ` parameters ` argument of ` TemplateExpressionSpec ` to specify learned category-specific parameters.
567+
568+ For example, let's say we want to learn an equation of the form:
584569
585570$$ y = \alpha \sin(x_1) + \beta $$
586571
587- for three different values of $\alpha$ and $\beta$.
572+ where $\alpha$ and $\beta$ are different for each category.
573+
574+ Further, let's say we have 3 categories,
575+ with $\alpha \in \{ 0.1, 1.5, -0.5\} $ and $\beta \in \{ 1.0, 2.0, 0.5\} $.
588576
589577``` python
590578import numpy as np
591- from pysr import PySRRegressor, ParametricExpressionSpec
579+ from pysr import PySRRegressor, TemplateExpressionSpec
592580
593- # Create data with 3 categories
581+ # Create data with 2 features and 3 categories
594582X = np.random.uniform(- 3 , 3 , (1000 , 2 ))
595583category = np.random.randint(0 , 3 , 1000 )
596584
@@ -603,34 +591,48 @@ y = np.array([
603591 scales[c] * np.sin(x1) + offsets[c]
604592 for x1, c in zip (X[:, 0 ], category)
605593])
594+ ```
595+
596+ Now, let's define our parametric expression:
606597
598+ ``` python
599+ template = TemplateExpressionSpec(
600+ expressions = [" f" ],
601+ variable_names = [" x1" , " x2" , " category" ],
602+ parameters = {" p1" : 3 , " p2" : 3 }, # One parameter per category
603+ combine = " f(x1, x2, p1[category], p2[category])"
604+ )
605+ ```
606+
607+ Next, we pass the category as a _ column_ in ` X `
608+ corresponding to the index we defined in ` variable_names ` .
609+
610+ ** Note that because Julia is 1-indexed, we need to add 1 to the category index.**
611+
612+ ``` python
613+ category_p_one = category + 1
614+ X_with_category = np.column_stack([X, category])
615+ ```
616+
617+ Now, we can fit our model:
618+
619+ ``` python
607620model = PySRRegressor(
608- expression_spec = ParametricExpressionSpec( max_parameters = 2 ) ,
621+ expression_spec = template ,
609622 binary_operators = [" +" , " *" , " -" , " /" ],
610623 unary_operators = [" sin" ],
611624 maxsize = 10 ,
612625)
613- model.fit(X , y, category = category )
626+ model.fit(X_with_category , y)
614627
615- # Predicting on new data:
616- # model.predict(X_test, category=category_test )
628+ # Predicting on new data
629+ # model.predict(X_test_with_category )
617630```
618631
619632See [ Expression Specifications] ( /api/#expression-specifications ) for more details.
620633
621- You can also use ` TemplateExpressionSpec ` in the same way, passing
622- the category as a column of ` X ` :
623-
624- ``` python
625- spec = TemplateExpressionSpec(
626- expressions = [" f" , " g" ],
627- variable_names = [" x1" , " x2" , " class" ],
628- parameters = {" p1" : 3 , " p2" : 3 },
629- combine = " p1[class] * sin(f(x1, x2)) + p2[class]" ,
630- )
631- ```
632-
633- this column will automatically be converted to integers.
634+ You can use this approach for more complex cases,
635+ where you have multiple expressions in the template and parameters that vary by category.
634636
635637
636638## 12. Using TensorBoard for Logging
0 commit comments