Skip to content

Commit

Permalink
Merge branch 'master' into dev3
Browse files Browse the repository at this point in the history
  • Loading branch information
MilesCranmer committed Feb 22, 2023
2 parents c428709 + a907ef1 commit b54efa5
Show file tree
Hide file tree
Showing 15 changed files with 550 additions and 947 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/CI.yml
Expand Up @@ -83,7 +83,6 @@ jobs:
shell: bash -l {0}
strategy:
matrix:
julia-version: ['1.7.1']
python-version: ['3.9']
os: ['ubuntu-latest']

Expand All @@ -108,7 +107,7 @@ jobs:
- name: "Cache Julia"
uses: julia-actions/cache@v1
with:
cache-name: ${{ matrix.os }}-conda-${{ matrix.julia-version }}-${{ matrix.python-version }}
cache-name: ${{ matrix.os }}-conda-${{ matrix.python-version }}
cache-packages: false
- name: "Install PySR"
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/CI_Windows.yml
Expand Up @@ -29,7 +29,7 @@ jobs:
shell: bash
strategy:
matrix:
julia-version: ['1.6', '1.8.2']
julia-version: ['1.8.2']
python-version: ['3.9']
os: [windows-latest]

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Expand Up @@ -27,7 +27,7 @@ jobs:
python-version: 3.9
cache: pip
- name: "Install packages for docs building"
run: pip install mkdocs-material mkdocs-autorefs 'mkdocstrings[python]' docstring_parser
run: pip install -r docs/requirements.txt
- name: "Install PySR"
run: pip install -e .
- name: "Build API docs"
Expand Down
7 changes: 1 addition & 6 deletions .github/workflows/pypi_deploy.yml
Expand Up @@ -3,17 +3,12 @@ on:
push:
tags:
- 'v*.*.*'
workflow_dispatch:

jobs:
pypi:
runs-on: ubuntu-latest
steps:
- name: Wait for tests to pass
uses: lewagon/wait-on-check-action@v1.2.0
with:
ref: ${{ github.ref }}
check-name: 'Linux'
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: "Checkout"
uses: actions/checkout@v3
- name: "Set up Python"
Expand Down
31 changes: 24 additions & 7 deletions README.md
Expand Up @@ -87,58 +87,70 @@ If none of these folders contain your Julia binary, then you need to add Julia's

# Introduction

Let's create a PySR example. First, let's import
numpy to generate some test data:
You might wish to try the interactive tutorial [here](https://colab.research.google.com/github/MilesCranmer/PySR/blob/master/examples/pysr_demo.ipynb), which uses the notebook in `examples/pysr_demo.ipynb`.

In practice, I highly recommend using IPython rather than Jupyter, as the printing is much nicer.
Below is a quick demo here which you can paste into a Python runtime.
First, let's import numpy to generate some test data:

```python
import numpy as np

X = 2 * np.random.randn(100, 5)
y = 2.5382 * np.cos(X[:, 3]) + X[:, 0] ** 2 - 0.5
```

We have created a dataset with 100 datapoints, with 5 features each.
The relation we wish to model is $2.5382 \cos(x_3) + x_0^2 - 0.5$.

Now, let's create a PySR model and train it.
PySR's main interface is in the style of scikit-learn:

```python
from pysr import PySRRegressor

model = PySRRegressor(
model_selection="best", # Result is mix of simplicity+accuracy
niterations=40,
niterations=40, # < Increase me for better results
binary_operators=["+", "*"],
unary_operators=[
"cos",
"exp",
"sin",
"inv(x) = 1/x",
# ^ Custom operator (julia syntax)
# ^ Custom operator (julia syntax)
],
extra_sympy_mappings={"inv": lambda x: 1 / x},
# ^ Define operator for SymPy as well
loss="loss(x, y) = (x - y)^2",
# ^ Custom loss function (julia syntax)
)
```

This will set up the model for 40 iterations of the search code, which contains hundreds of thousands of mutations and equation evaluations.

Let's train this model on our dataset:

```python
model.fit(X, y)
```

Internally, this launches a Julia process which will do a multithreaded search for equations to fit the dataset.

Equations will be printed during training, and once you are satisfied, you may
quit early by hitting 'q' and then \<enter\>.

After the model has been fit, you can run `model.predict(X)`
to see the predictions on a given dataset.
to see the predictions on a given dataset using the automatically-selected expression,
or, for example, `model.predict(X, 3)` to see the predictions of the 3rd equation.

You may run:

```python
print(model)
```

to print the learned equations:

```python
PySRRegressor.equations_ = [
pick score equation loss complexity
Expand All @@ -150,6 +162,7 @@ PySRRegressor.equations_ = [
5 >>>> inf (((cos(x3) + -0.19699033) * 2.5382123) + (x0 *... 0.000000 10
]
```

This arrow in the `pick` column indicates which equation is currently selected by your
`model_selection` strategy for prediction.
(You may change `model_selection` after `.fit(X, y)` as well.)
Expand All @@ -165,6 +178,7 @@ This will cause problems if significant changes are made to the search parameter
You will notice that PySR will save two files: `hall_of_fame...csv` and `hall_of_fame...pkl`.
The csv file is a list of equations and their losses, and the pkl file is a saved state of the model.
You may load the model from the `pkl` file with:

```python
model = PySRRegressor.from_file("hall_of_fame.2022-08-10_100832.281.pkl")
```
Expand Down Expand Up @@ -254,22 +268,25 @@ model = PySRRegressor(
)
```


# Docker

You can also test out PySR in Docker, without
installing it locally, by running the following command in
the root directory of this repo:

```bash
docker build -t pysr .
```

This builds an image called `pysr` for your system's architecture,
which also contains IPython.

You can then run this with:

```bash
docker run -it --rm -v "$PWD:/data" pysr ipython
```

which will link the current directory to the container's `/data` directory
and then launch ipython.

Expand Down
8 changes: 8 additions & 0 deletions docs/README.md
@@ -0,0 +1,8 @@
# PySR Documentation

## Building locally

1. In the base directory, run `pip install -r docs/requirements.txt`.
2. Install PySR in editable mode: `pip install -e .`.
3. Build doc source with `cd docs && ./gen_docs.sh && cd ..`.
4. Create and serve docs with mkdocs: `mkdocs serve -w pysr`.
10 changes: 6 additions & 4 deletions docs/examples.md
Expand Up @@ -249,9 +249,11 @@ Next, let's use this list of primes to create a dataset of $x, y$ pairs:
import numpy as np

X = np.random.randint(0, 100, 100)[:, None]
y = [primes[3*X[i, 0] + 1] - 5 for i in range(100)]
y = [primes[3*X[i, 0] + 1] - 5 + np.random.randn()*0.001 for i in range(100)]
```

Note that we have also added a tiny bit of noise to the dataset.

Finally, let's create a PySR model, and pass the custom operator. We also need to define the sympy equivalent, which we can leave as a placeholder for now:

```python
Expand All @@ -264,7 +266,7 @@ class sympy_p(sympy.Function):
model = PySRRegressor(
binary_operators=["+", "-", "*", "/"],
unary_operators=["p"],
niterations=1000,
niterations=100,
extra_sympy_mappings={"p": sympy_p}
)
```
Expand All @@ -276,10 +278,10 @@ model.fit(X, y)
```

if all works out, you should be able to see the true relation (note that the constant offset might not be exactly 1, since it is allowed to round to the nearest integer).
You can get the sympy version of the last row with:
You can get the sympy version of the best equation with:

```python
model.sympy(index=-1)
model.sympy()
```

## 8. Additional features
Expand Down
11 changes: 11 additions & 0 deletions docs/interactive-docs.md
@@ -0,0 +1,11 @@
# Interactive Reference ⭐

<!-- Display content from `astroautomata.com/pysr_interactive` -->

The following docs are interactive, and, based on your selections,
will create a snippet of Python code at the bottom which you can execute locally.
Clicking on each parameter's name will display a description.
Note that this is an incomplete list of options; for the full list,
see the [API Reference](api.md).

<embed src="https://astroautomata.com/pysr_interactive" width="100%" height="2000px" />
4 changes: 4 additions & 0 deletions docs/requirements.txt
@@ -0,0 +1,4 @@
mkdocs-material
mkdocs-autorefs
mkdocstrings[python]
docstring_parser

0 comments on commit b54efa5

Please sign in to comment.