Merge branch 'main' into add_upload_study_artifact_api

This commit is contained in:
gen740
2023-10-20 18:28:42 +09:00
29 changed files with 390 additions and 175 deletions
@@ -1,10 +1,10 @@
name: e2e-tests
name: e2e-dashboard-tests
on:
pull_request:
branches:
- main
paths:
- '.github/workflows/e2e-tests.yml'
- '.github/workflows/e2e-dashboard-tests.yml'
- '**.py'
- '**.ts'
- '**.tsx'
@@ -47,4 +47,4 @@ jobs:
run: playwright install
- name: Run e2e tests
run: pytest e2e_tests
run: pytest e2e_tests/test_dashboard
@@ -0,0 +1,51 @@
name: e2e-standalone-tests
on:
pull_request:
branches:
- main
paths:
- '.github/workflows/e2e-standalone-tests.yml'
- '**.py'
- '**.ts'
- '**.tsx'
- 'package.json'
- 'package-lock.json'
- 'tsconfig.json'
jobs:
test:
runs-on: ubuntu-20.04
strategy:
matrix:
optuna-version: ['optuna==2.10.0', 'git+https://github.com/optuna/optuna.git']
steps:
- uses: actions/checkout@v3
- name: Install Rust toolchains
uses: dtolnay/rust-toolchain@stable
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Setup Node
uses: actions/setup-node@v2
with:
node-version: '18'
- name: Setup Optuna ${{ matrix.optuna-version }}
run: |
python -m pip install --progress-bar off --upgrade pip setuptools
python -m pip install --progress-bar off --upgrade ${{ matrix.optuna-version }}
- name: Install dependencies
run: |
python -m pip install --progress-bar off .
python -m pip install --progress-bar off pytest-playwright
- name: Build standalone_app
run: make MODE="prd" standalone_app/public/bundle.js
- name: Install the required browsers
run: playwright install
- name: Run e2e tests
run: pytest e2e_tests/test_standalone
+1
View File
@@ -6,6 +6,7 @@ on:
paths:
- '.github/workflows/python-tests.yml'
- '**.py'
- 'pyproject.toml'
jobs:
lint:
runs-on: ubuntu-latest
+13 -1
View File
@@ -77,6 +77,18 @@ $ docker run -it --rm -p 8080:8080 ghcr.io/optuna/optuna-dashboard postgresql+ps
</details>
## Jupyter Lab Extension (Experimental)
You can install the Jupyter Lab extension via [PyPI](https://pypi.org/project/jupyterlab-optuna/).
```
$ pip install jupyterlab jupyterlab-optuna
```
<img src="./docs/_static/jupyterlab-extension.png" style="width:600px;" alt="Jupyter Lab Extension">
To use, click the tile to launch the extension, and enter your Optunas storage URL (e.g. `sqlite:///db.sqlite3`) in the dialog.
## Browser-only version (Experimental)
<img src="./docs/_static/browser-app.gif" style="width:600px;" alt="Browser-only version">
@@ -93,7 +105,7 @@ https://optuna.github.io/optuna-dashboard/
You can install the VS Code extension via [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=Optuna.optuna-dashboard#overview).
<img src="./docs/_static/vscode-extension.png" style="width:600px;" alt="VSCode Extension">
<img src="./docs/_static/vscode-extension.png" style="width:600px;" alt="VS Code Extension">
Please right-click the SQLite3 files (`*.db` or `*.sqlite3`) in the VS Code file explorer and select the "Open in Optuna Dashboard" command from the dropdown menu.
This extension leverages the browser-only version of Optuna Dashboard, so the same limitations apply.
Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

+13
View File
@@ -178,6 +178,19 @@ or
$ pip install uwsgi
$ uwsgi --http :8080 --workeers 4 --wsgi-file wsgi.py
Jupyter Lab Extension (Experimental)
--------------------------------
You can install the Jupyter Lab extension via `PyPI <https://pypi.org/project/jupyterlab-optuna/>`_.
.. figure:: _static/jupyterlab-extension.png
:alt: Screenshot for the Jupyter Lab Extension
:align: center
:width: 800px
Jupyter Lab Extension
To use, click the tile to launch the extension, and enter your Optunas storage URL (e.g. ``sqlite:///db.sqlite3``) in the dialog.
Browser-only version (Experimental)
-----------------------------------
+1 -1
View File
@@ -27,7 +27,7 @@ First, ensure the necessary packages are installed by executing the following co
.. code-block:: console
$ pip install "optuna>=3.3.0" "optuna-dashboard>=0.13.0b1" pillow botorch
$ pip install "optuna>=3.3.0" "optuna-dashboard[preferential]>=0.13.0b1" pillow
Next, execute the Python script, copied from `generator.py`_.
@@ -2,7 +2,7 @@ import optuna
from playwright.sync_api import Page
import pytest
from ..test_server import make_test_server
from ...test_server import make_test_server
def make_test_storage() -> optuna.storages.InMemoryStorage:
@@ -4,7 +4,7 @@ import optuna
from playwright.sync_api import Page
import pytest
from .test_server import make_test_server
from ..test_server import make_test_server
@pytest.fixture
+28
View File
@@ -1,4 +1,6 @@
import http.server
import socket
import socketserver
import threading
from wsgiref.simple_server import make_server
@@ -33,3 +35,29 @@ def make_test_server(
request.addfinalizer(stop_server)
return f"http://{addr}:{port}/dashboard"
def make_standalone_server(request: pytest.FixtureRequest) -> str:
addr = "127.0.0.1"
port = get_free_port()
directory = "./standalone_app/"
Handler = http.server.SimpleHTTPRequestHandler
httpd = socketserver.TCPServer(
("", port), lambda *args, **kwargs: Handler(*args, directory=directory, **kwargs)
)
def serve_httpd():
httpd.serve_forever()
thread = threading.Thread(target=serve_httpd)
thread.start()
def stop_server() -> None:
httpd.shutdown()
httpd.server_close()
thread.join()
request.addfinalizer(stop_server)
return f"http://{addr}:{port}"
@@ -0,0 +1,22 @@
from playwright.sync_api import Page
import pytest
from ..test_server import make_standalone_server
@pytest.fixture
def server_url(request: pytest.FixtureRequest) -> str:
return make_standalone_server(request)
def test_home(
page: Page,
server_url: str,
) -> None:
url = f"{server_url}"
page.goto(url)
element = page.get_by_role("heading")
assert element is not None
title = element.text_content()
assert title is not None
assert title == "Optuna Dashboard (Wasm ver.)"
+1 -1
View File
@@ -17,4 +17,4 @@ from ._note import save_note # noqa
from ._preference_setting import register_preference_feedback_component # noqa
__version__ = "0.13.0b1"
__version__ = "0.13.0"
+23 -15
View File
@@ -7,9 +7,9 @@ from typing import Iterable
import optuna
from optuna import logging
from optuna._imports import try_import
from optuna.distributions import BaseDistribution
from optuna.samplers import BaseSampler
from optuna.samplers import RandomSampler
from optuna.trial import FrozenTrial
from optuna.trial import TrialState
from optuna_dashboard.preferential._system_attrs import get_n_generate
@@ -20,6 +20,10 @@ from optuna_dashboard.preferential._system_attrs import report_preferences
from optuna_dashboard.preferential._system_attrs import set_n_generate
with try_import() as _imports:
from optuna_dashboard.preferential.samplers.gp import PreferentialGPSampler
_logger = logging.get_logger(__name__)
_SYSTEM_ATTR_PREFERENTIAL_STUDY = "preference:is_preferential"
@@ -344,11 +348,10 @@ def create_study(
sampler:
A sampler object that implements background algorithm for value suggestion.
If :obj:`None` is specified, `RandomSampler`_ is used. Please note that
most Optuna samplers does not work efficiently for preferential optimization.
.. _RandomSampler: https://optuna.readthedocs.io/en/stable/reference/\
samplers/generated/optuna.samplers.RandomSampler.html
If :obj:`None` is specified,
:class:`~optuna_dashboard.preferential.samplers.gp.PreferentialGPSampler` is used.
Please note that most Optuna samplers does not work efficiently for preferential
optimization.
study_name:
Study's name. If this argument is set to None, a unique name is generated
@@ -369,9 +372,13 @@ def create_study(
The interface may change in newer versions without prior notice.
"""
try:
if sampler is None:
_imports.check() # If BoTorch is not installed, raise ImportError.
sampler = PreferentialGPSampler()
study = optuna.create_study(
storage=storage,
sampler=sampler or RandomSampler(),
sampler=sampler,
study_name=study_name,
)
study._storage.set_study_system_attr(
@@ -441,11 +448,10 @@ def load_study(
:func:`~optuna.study.create_study` for further details.
sampler:
A sampler object that implements background algorithm for value suggestion.
If :obj:`None` is specified, `RandomSampler`_ is used. Please note that
most Optuna samplers does not work efficiently for preferential optimization.
.. _RandomSampler: https://optuna.readthedocs.io/en/stable/reference/samplers/\
generated/optuna.samplers.RandomSampler.html
If :obj:`None` is specified,
:class:`~optuna_dashboard.preferential.samplers.gp.PreferentialGPSampler` is used.
Please note that most Optuna samplers does not work efficiently for preferential
optimization.
Returns:
A :class:`~optuna_dashboard.preferential.PreferentialStudy` object.
@@ -454,9 +460,11 @@ def load_study(
Preferential optimization is an experimental feature (introduced in v0.13.0).
The interface may change in newer versions without prior notice.
"""
study = optuna.load_study(
study_name=study_name, storage=storage, sampler=sampler or RandomSampler()
)
if sampler is None:
_imports.check() # If BoTorch is not installed, raise ImportError.
sampler = PreferentialGPSampler()
study = optuna.load_study(study_name=study_name, storage=storage, sampler=sampler)
system_attrs = study._storage.get_study_system_attrs(study._study_id)
if not system_attrs.get(_SYSTEM_ATTR_PREFERENTIAL_STUDY):
raise ValueError("The study is not a PreferentialStudy.")
@@ -147,6 +147,16 @@ const CandidateTrial: FC<{
overflow: "auto",
}}
>
<IconButton
sx={{
position: "absolute",
top: theme.spacing(2),
right: theme.spacing(2),
}}
onClick={() => setDetailShown(false)}
>
<ClearIcon />
</IconButton>
<TrialListDetail
trial={trial}
isBestTrial={() => false}
+1 -2
View File
@@ -64,8 +64,7 @@ export const StudyList: FC<{
return useMemo(() => new URLSearchParams(search), [search])
}
const query = useQuery()
const initialSortBy =
query.get("studies_order_by") === "desc" ? "desc" : "asc"
const initialSortBy = query.get("studies_order_by") === "asc" ? "asc" : "desc"
const [sortBy, setSortBy] = useState<"asc" | "desc">(initialSortBy)
let filteredStudies = studies.filter((s) => !studyFilter(s))
@@ -5,7 +5,9 @@ import { GizmoHelper, GizmoViewport, OrbitControls } from "@react-three/drei"
import { STLLoader } from "three/examples/jsm/loaders/STLLoader"
import { Rhino3dmLoader } from "three/examples/jsm/loaders/3DMLoader"
import { PerspectiveCamera } from "three"
import { Modal, Box } from "@mui/material"
import { Modal, Box, useTheme } from "@mui/material"
import ClearIcon from "@mui/icons-material/Clear"
import IconButton from "@mui/material/IconButton"
export const isThreejsArtifact = (artifact: Artifact): boolean => {
return (
@@ -32,7 +34,7 @@ const CustomGizmoHelper: React.FC = () => {
)
}
const calculateBoundingBox = (geometries: THREE.BufferGeometry[]) => {
const computeBoundingBox = (geometries: THREE.BufferGeometry[]) => {
const boundingBox = new THREE.Box3()
geometries.forEach((geometry) => {
const mesh = new THREE.Mesh(geometry)
@@ -45,8 +47,11 @@ export const ThreejsArtifactViewer: React.FC<ThreejsArtifactViewerProps> = (
props
) => {
const [geometry, setGeometry] = useState<THREE.BufferGeometry[]>([])
const [modelSize, setModelSize] = useState<THREE.Vector3>(
new THREE.Vector3(10, 10, 10)
const [boundingBox, setBoundingBox] = useState<THREE.Box3>(
new THREE.Box3(
new THREE.Vector3(-10, -10, -10),
new THREE.Vector3(10, 10, 10)
)
)
const [cameraSettings, setCameraSettings] = useState<PerspectiveCamera>(
new THREE.PerspectiveCamera()
@@ -54,11 +59,11 @@ export const ThreejsArtifactViewer: React.FC<ThreejsArtifactViewerProps> = (
const handleLoadedGeometries = (geometries: THREE.BufferGeometry[]) => {
setGeometry(geometries)
const boundingBox = calculateBoundingBox(geometries)
const boundingBox = computeBoundingBox(geometries)
if (boundingBox !== null) {
const size = boundingBox.getSize(new THREE.Vector3())
setModelSize(size)
setBoundingBox(boundingBox)
}
return boundingBox
}
useEffect(() => {
@@ -81,20 +86,30 @@ export const ThreejsArtifactViewer: React.FC<ThreejsArtifactViewerProps> = (
}
})
}
const maxModelSize = Math.max(modelSize.x, modelSize.y, modelSize.z)
const cameraSet = new THREE.PerspectiveCamera(
modelSize
? Math.min(
45,
Math.atan(modelSize.y / modelSize.z) * (180 / Math.PI) * 2
)
: 45,
window.innerWidth / window.innerHeight
)
cameraSet.position.set(maxModelSize * 2, maxModelSize * 2, maxModelSize * 2)
setCameraSettings(cameraSet)
}, [])
useEffect(() => {
const cameraSet = new THREE.PerspectiveCamera(
50,
window.innerWidth / window.innerHeight,
0.1,
boundingBox.getSize(new THREE.Vector3()).length() * 100
)
const maxPosition = Math.max(
boundingBox.max.x,
boundingBox.max.y,
boundingBox.max.z
)
cameraSet.position.set(
maxPosition * 1.5,
maxPosition * 1.5,
maxPosition * 1.5
)
const center = boundingBox.getCenter(new THREE.Vector3())
cameraSet.lookAt(center.x, center.y, center.z)
setCameraSettings(cameraSet)
}, [boundingBox])
return (
<Canvas
camera={cameraSettings}
@@ -102,7 +117,7 @@ export const ThreejsArtifactViewer: React.FC<ThreejsArtifactViewerProps> = (
>
<ambientLight />
<OrbitControls />
<gridHelper args={[Math.max(modelSize?.x, modelSize?.y) * 5]} />
<gridHelper args={[Math.max(boundingBox.max.x, boundingBox.max.y) * 5]} />
{props.hasGizmo && <CustomGizmoHelper />}
<axesHelper />
{geometry.length > 0 &&
@@ -121,6 +136,7 @@ export const useThreejsArtifactModal = (): [
] => {
const [open, setOpen] = useState(false)
const [target, setTarget] = useState<[string, Artifact | null]>(["", null])
const theme = useTheme()
const openModal = (artifactUrlPath: string, artifact: Artifact) => {
setTarget([artifactUrlPath, artifact])
@@ -146,6 +162,19 @@ export const useThreejsArtifactModal = (): [
borderRadius: "15px",
}}
>
<IconButton
sx={{
position: "absolute",
top: theme.spacing(2),
right: theme.spacing(2),
}}
onClick={() => {
setOpen(false)
setTarget(["", null])
}}
>
<ClearIcon />
</IconButton>
<ThreejsArtifactViewer
src={target[0]}
width={`${innerWidth * 0.8}px`}
+124 -120
View File
@@ -75,11 +75,12 @@
}
},
"node_modules/@babel/code-frame": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
"integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
"version": "7.22.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
"integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
"dependencies": {
"@babel/highlight": "^7.18.6"
"@babel/highlight": "^7.22.13",
"chalk": "^2.4.2"
},
"engines": {
"node": ">=6.9.0"
@@ -125,13 +126,14 @@
}
},
"node_modules/@babel/generator": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz",
"integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
"dev": true,
"dependencies": {
"@babel/types": "^7.20.5",
"@babel/types": "^7.23.0",
"@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
},
"engines": {
@@ -250,9 +252,9 @@
}
},
"node_modules/@babel/helper-environment-visitor": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
"integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
"integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
"dev": true,
"engines": {
"node": ">=6.9.0"
@@ -271,25 +273,25 @@
}
},
"node_modules/@babel/helper-function-name": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
"integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
"integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
"dev": true,
"dependencies": {
"@babel/template": "^7.18.10",
"@babel/types": "^7.19.0"
"@babel/template": "^7.22.15",
"@babel/types": "^7.23.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-hoist-variables": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
"integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
"integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
"dev": true,
"dependencies": {
"@babel/types": "^7.18.6"
"@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
@@ -417,29 +419,29 @@
}
},
"node_modules/@babel/helper-split-export-declaration": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
"integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
"integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
"dev": true,
"dependencies": {
"@babel/types": "^7.18.6"
"@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.19.4",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
"integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==",
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.19.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
"integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
"integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
"engines": {
"node": ">=6.9.0"
}
@@ -483,12 +485,12 @@
}
},
"node_modules/@babel/highlight": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
"integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
"integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
"dependencies": {
"@babel/helper-validator-identifier": "^7.18.6",
"chalk": "^2.0.0",
"@babel/helper-validator-identifier": "^7.22.20",
"chalk": "^2.4.2",
"js-tokens": "^4.0.0"
},
"engines": {
@@ -496,9 +498,9 @@
}
},
"node_modules/@babel/parser": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz",
"integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
"dev": true,
"bin": {
"parser": "bin/babel-parser.js"
@@ -1657,33 +1659,33 @@
}
},
"node_modules/@babel/template": {
"version": "7.18.10",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
"integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
"integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.18.6",
"@babel/parser": "^7.18.10",
"@babel/types": "^7.18.10"
"@babel/code-frame": "^7.22.13",
"@babel/parser": "^7.22.15",
"@babel/types": "^7.22.15"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz",
"integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==",
"version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.18.6",
"@babel/generator": "^7.20.5",
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-function-name": "^7.19.0",
"@babel/helper-hoist-variables": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6",
"@babel/parser": "^7.20.5",
"@babel/types": "^7.20.5",
"@babel/code-frame": "^7.22.13",
"@babel/generator": "^7.23.0",
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-function-name": "^7.23.0",
"@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"@babel/parser": "^7.23.0",
"@babel/types": "^7.23.0",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@@ -1692,12 +1694,12 @@
}
},
"node_modules/@babel/types": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz",
"integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
"dependencies": {
"@babel/helper-string-parser": "^7.19.4",
"@babel/helper-validator-identifier": "^7.19.1",
"@babel/helper-string-parser": "^7.22.5",
"@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0"
},
"engines": {
@@ -15313,11 +15315,12 @@
}
},
"@babel/code-frame": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
"integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
"version": "7.22.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
"integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
"requires": {
"@babel/highlight": "^7.18.6"
"@babel/highlight": "^7.22.13",
"chalk": "^2.4.2"
}
},
"@babel/compat-data": {
@@ -15350,13 +15353,14 @@
}
},
"@babel/generator": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz",
"integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
"dev": true,
"requires": {
"@babel/types": "^7.20.5",
"@babel/types": "^7.23.0",
"@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
},
"dependencies": {
@@ -15444,9 +15448,9 @@
}
},
"@babel/helper-environment-visitor": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
"integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
"integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
"dev": true
},
"@babel/helper-explode-assignable-expression": {
@@ -15459,22 +15463,22 @@
}
},
"@babel/helper-function-name": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
"integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
"integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
"dev": true,
"requires": {
"@babel/template": "^7.18.10",
"@babel/types": "^7.19.0"
"@babel/template": "^7.22.15",
"@babel/types": "^7.23.0"
}
},
"@babel/helper-hoist-variables": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
"integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
"integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
"dev": true,
"requires": {
"@babel/types": "^7.18.6"
"@babel/types": "^7.22.5"
}
},
"@babel/helper-member-expression-to-functions": {
@@ -15569,23 +15573,23 @@
}
},
"@babel/helper-split-export-declaration": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
"integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
"integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
"dev": true,
"requires": {
"@babel/types": "^7.18.6"
"@babel/types": "^7.22.5"
}
},
"@babel/helper-string-parser": {
"version": "7.19.4",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
"integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw=="
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw=="
},
"@babel/helper-validator-identifier": {
"version": "7.19.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
"integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w=="
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
"integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A=="
},
"@babel/helper-validator-option": {
"version": "7.18.6",
@@ -15617,19 +15621,19 @@
}
},
"@babel/highlight": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
"integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
"integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
"requires": {
"@babel/helper-validator-identifier": "^7.18.6",
"chalk": "^2.0.0",
"@babel/helper-validator-identifier": "^7.22.20",
"chalk": "^2.4.2",
"js-tokens": "^4.0.0"
}
},
"@babel/parser": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz",
"integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
"dev": true
},
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
@@ -16401,41 +16405,41 @@
}
},
"@babel/template": {
"version": "7.18.10",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
"integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
"integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.18.6",
"@babel/parser": "^7.18.10",
"@babel/types": "^7.18.10"
"@babel/code-frame": "^7.22.13",
"@babel/parser": "^7.22.15",
"@babel/types": "^7.22.15"
}
},
"@babel/traverse": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz",
"integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==",
"version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.18.6",
"@babel/generator": "^7.20.5",
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-function-name": "^7.19.0",
"@babel/helper-hoist-variables": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6",
"@babel/parser": "^7.20.5",
"@babel/types": "^7.20.5",
"@babel/code-frame": "^7.22.13",
"@babel/generator": "^7.23.0",
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-function-name": "^7.23.0",
"@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"@babel/parser": "^7.23.0",
"@babel/types": "^7.23.0",
"debug": "^4.1.0",
"globals": "^11.1.0"
}
},
"@babel/types": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz",
"integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
"requires": {
"@babel/helper-string-parser": "^7.19.4",
"@babel/helper-validator-identifier": "^7.19.1",
"@babel/helper-string-parser": "^7.22.5",
"@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0"
}
},
+4 -1
View File
@@ -52,9 +52,12 @@ test = [
optional = [
"streamlit",
"boto3",
"botorch",
"botorch>=0.8.1; python_version>='3.8'",
]
preferential = [
"botorch>=0.8.1",
]
[project.scripts]
optuna-dashboard = "optuna_dashboard._cli:main"
+5
View File
@@ -3,6 +3,7 @@ from __future__ import annotations
import copy
import multiprocessing
import pickle
import sys
from typing import Callable
from unittest.mock import patch
import uuid
@@ -22,6 +23,10 @@ from ..storage_supplier import parametrize_storages
from ..storage_supplier import StorageSupplier
if sys.version_info < (3, 8):
pytest.skip("BoTorch dropped Python3.7 support", allow_module_level=True)
@parametrize_storages
def test_study_set_and_get_user_attrs(storage_supplier: Callable[[], StorageSupplier]) -> None:
with storage_supplier() as storage:
+9
View File
@@ -1,6 +1,7 @@
from __future__ import annotations
import json
import sys
from unittest import TestCase
import optuna
@@ -14,6 +15,7 @@ from optuna_dashboard._preferential_history import remove_history
from optuna_dashboard._preferential_history import report_history
from optuna_dashboard._serializer import serialize_preference_history
from optuna_dashboard.preferential import create_study
import pytest
from .wsgi_client import send_request
@@ -105,6 +107,7 @@ class APITestCase(TestCase):
)
self.assertEqual(status, 400)
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
def test_get_best_trials_of_preferential_study(self) -> None:
storage = optuna.storages.InMemoryStorage()
study = create_study(n_generate=4, storage=storage)
@@ -128,6 +131,7 @@ class APITestCase(TestCase):
assert len(best_trials) == 1
assert best_trials[0]["number"] == 0
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
def test_report_preference(self) -> None:
storage = optuna.storages.InMemoryStorage()
study = create_study(n_generate=4, storage=storage)
@@ -161,6 +165,7 @@ class APITestCase(TestCase):
assert better.number == 2
assert worse.number == 1
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
def test_report_preference_when_typo_mode(self) -> None:
storage = optuna.storages.InMemoryStorage()
study = create_study(storage=storage, n_generate=3)
@@ -184,6 +189,7 @@ class APITestCase(TestCase):
)
self.assertEqual(status, 400)
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
def test_change_component(self) -> None:
storage = optuna.storages.InMemoryStorage()
study = create_study(storage=storage, n_generate=3)
@@ -214,6 +220,7 @@ class APITestCase(TestCase):
assert study_detail["feedback_component_type"]["output_type"] == "artifact"
assert study_detail["feedback_component_type"]["artifact_key"] == "image"
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
def test_skip_trial(self) -> None:
storage = optuna.storages.InMemoryStorage()
study = create_study(n_generate=4, storage=storage)
@@ -238,6 +245,7 @@ class APITestCase(TestCase):
assert len(best_trials) == 1
assert best_trials[0].number == 2
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
def test_remove_history(self) -> None:
storage = optuna.storages.InMemoryStorage()
study = create_study(storage=storage, n_generate=3)
@@ -271,6 +279,7 @@ class APITestCase(TestCase):
assert histories[0]["is_removed"]
assert len(study.get_preferences()) == 0
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
def test_restore_history(self) -> None:
storage = optuna.storages.InMemoryStorage()
study = create_study(storage=storage, n_generate=3)
@@ -1,6 +1,7 @@
from __future__ import annotations
import json
import sys
from typing import Callable
from typing import TYPE_CHECKING
@@ -13,6 +14,7 @@ from optuna_dashboard._preferential_history import restore_history
from optuna_dashboard._serializer import serialize_preference_history
from optuna_dashboard.preferential import create_study
from optuna_dashboard.preferential._system_attrs import _SYSTEM_ATTR_PREFIX_PREFERENCE
import pytest
from .storage_supplier import parametrize_storages
from .storage_supplier import StorageSupplier
@@ -22,6 +24,10 @@ if TYPE_CHECKING:
from optuna_dashboard._preferential_history import History
if sys.version_info < (3, 8):
pytest.skip("BoTorch dropped Python3.7 support", allow_module_level=True)
@parametrize_storages
def test_report_and_get_choices(storage_supplier: Callable[[], StorageSupplier]) -> None:
with storage_supplier() as storage:
+5
View File
@@ -1,11 +1,14 @@
from __future__ import annotations
import sys
import optuna
from optuna_dashboard._serializer import serialize_attrs
from optuna_dashboard._serializer import serialize_study_detail
from optuna_dashboard._serializer import serialize_study_summary
from optuna_dashboard._storage import get_study_summaries
from optuna_dashboard.preferential import create_study
import pytest
def test_serialize_bytes() -> None:
@@ -22,6 +25,7 @@ def test_serialize_dict() -> None:
assert len(serialized) <= 1
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
def test_get_study_detail_is_preferential() -> None:
storage = optuna.storages.InMemoryStorage()
study = create_study(n_generate=4, storage=storage)
@@ -48,6 +52,7 @@ def test_get_study_detail_is_not_preferential() -> None:
assert not study_detail["is_preferential"]
@pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support")
def test_get_study_summary_is_preferential() -> None:
storage = optuna.storages.InMemoryStorage()
create_study(n_generate=4, storage=storage)
+13 -8
View File
@@ -1,16 +1,20 @@
use fanova::{FanovaOptions, RandomForestOptions};
use js_sys::Array;
use serde_wasm_bindgen::from_value;
use fanova::{FanovaOptions, RandomForestOptions};
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn wasm_fanova_calculate(features: Array, targets: Array) -> Vec<f64> {
// TODO(c-bata): Fix error handling
pub fn wasm_fanova_calculate(features: Array, targets: Array) -> Result<Vec<f64>, JsError> {
let features_vec: Vec<Vec<f64>> = features
.iter()
.map(|x| from_value::<Vec<f64>>(x).unwrap())
.collect();
let targets_vec: Vec<f64> = targets.iter().map(|x| x.as_f64().unwrap()).collect();
.map(|x| from_value::<Vec<f64>>(x))
.collect::<Result<_, _>>()
.map_err(|_| JsError::new("features must be of type number[][]"))?;
let targets_vec: Vec<f64> = targets
.iter()
.map(|x| x.as_f64())
.collect::<Option<_>>()
.ok_or(JsError::new("targets must be of type number[]"))?;
let mut fanova = FanovaOptions::new()
.random_forest(RandomForestOptions::new().seed(0))
@@ -18,9 +22,10 @@ pub fn wasm_fanova_calculate(features: Array, targets: Array) -> Vec<f64> {
features_vec.iter().map(|x| x.as_slice()).collect(),
&targets_vec,
)
.unwrap();
.map_err(|e| JsError::new(&format!("failed to build fANOVA model: {}", e)))?;
let importances = (0..features_vec.len())
.map(|i| fanova.quantify_importance(&[i]).mean)
.collect::<Vec<_>>();
return importances;
Ok(importances)
}
@@ -39,6 +39,7 @@ export const PlotImportance: FC<{ study: Study }> = ({ study }) => {
const values = filteredTrials.map(
(t) => t.values?.[objectiveId] as number
)
// TODO: handle errors thrown by wasm_fanova_calculate
const importance = wasm_fanova_calculate(features, values)
return study.intersection_search_space.map((s, i) => ({
name: s.name,
+4
View File
@@ -14,6 +14,10 @@ Nothing to configure.
## Release Notes
### 0.1.0
Added older database schemas support (Optuna 2.6.0 or later)
### 0.0.1
Initial Release
+1 -1
View File
@@ -3,7 +3,7 @@
"displayName": "Optuna Dashboard",
"description": "Web Dashboard for Optuna",
"publisher": "Optuna",
"version": "0.0.1",
"version": "0.1.0",
"license": "MIT",
"icon": "images/optuna-logo.png",
"engines": {