Merge pull request #862 from porink0424/feat/separate-react-component

Separated UI components into `@optuna/react` (Continued from #851)
This commit is contained in:
c-bata
2024-04-12 12:44:58 +09:00
committed by GitHub
23 changed files with 1069 additions and 1043 deletions
+12
View File
@@ -24,6 +24,7 @@
"react-router-dom": "^6.22.3"
},
"devDependencies": {
"@optuna/types": "../tslib/types",
"@types/plotly.js": "^2.29.2",
"@types/react": "^18.2.64",
"@types/react-dom": "^18.2.21",
@@ -68,6 +69,7 @@
"@storybook/react": "^8.0.4",
"@storybook/react-vite": "^8.0.4",
"@storybook/test": "^8.0.4",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.2.2",
"@types/plotly.js-dist-min": "^2.3.4",
"@types/react": "^18.2.55",
@@ -91,6 +93,12 @@
"@optuna/types": "../types/"
}
},
"../tslib/types": {
"name": "@optuna/types",
"version": "0.0.1",
"dev": true,
"license": "MIT"
},
"node_modules/@ampproject/remapping": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
@@ -1338,6 +1346,10 @@
"resolved": "../tslib/storage",
"link": true
},
"node_modules/@optuna/types": {
"resolved": "../tslib/types",
"link": true
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
+1
View File
@@ -8,6 +8,7 @@
"build:vscode": "webpack"
},
"devDependencies": {
"@optuna/types": "../tslib/types",
"@types/plotly.js": "^2.29.2",
"@types/react": "^18.2.64",
"@types/react-dom": "^18.2.21",
+73 -4
View File
@@ -13,11 +13,16 @@ import {
useTheme,
} from "@mui/material"
import Grid2 from "@mui/material/Unstable_Grid2"
import { PlotHistory, TrialTable } from "@optuna/react"
import {
PlotHistory,
PlotImportance,
PlotIntermediateValues,
TrialTable,
} from "@optuna/react"
import * as Optuna from "@optuna/types"
import init, { wasm_fanova_calculate } from "optuna"
import React, { FC, useContext, useState, useEffect } from "react"
import { Link, useParams } from "react-router-dom"
import { PlotImportance } from "./PlotImportance"
import { PlotIntermediateValues } from "./PlotIntermediateValues"
import { StorageContext } from "./StorageProvider"
export const StudyDetail: FC<{
@@ -40,6 +45,68 @@ export const StudyDetail: FC<{
fetchStudy()
}, [storage, idxNumber])
const [importance, setImportance] = useState<Optuna.ParamImportance[][]>([])
const filterFunc = (trial: Optuna.Trial, objectiveId: number): boolean => {
if (trial.state !== "Complete" && trial.state !== "Pruned") {
return false
}
if (trial.values === undefined) {
return false
}
return (
trial.values.length > objectiveId &&
trial.values[objectiveId] !== Infinity &&
trial.values[objectiveId] !== -Infinity
)
}
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
useEffect(() => {
async function run_wasm() {
if (study === null) {
return
}
await init()
const x: Optuna.ParamImportance[][] = study.directions.map(
(_d, objectiveId) => {
const filteredTrials = study.trials.filter((t) =>
filterFunc(t, objectiveId)
)
if (filteredTrials.length === 0) {
return study.union_search_space.map((s) => {
return {
name: s.name,
importance: 0.5,
}
})
}
const features = study.intersection_search_space.map((s) =>
filteredTrials
.map(
(t) =>
t.params.find((p) => p.name === s.name) as Optuna.TrialParam
)
.map((p) => p.param_internal_value)
)
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,
importance: importance[i],
}))
}
)
setImportance(x)
}
run_wasm()
}, [study])
return (
<>
<AppBar position="static">
@@ -113,7 +180,9 @@ export const StudyDetail: FC<{
<Grid2 xs={6}>
<Card sx={{ margin: theme.spacing(2) }}>
<CardContent>
{!!study && <PlotImportance study={study} />}
{!!study && (
<PlotImportance study={study} importance={importance} />
)}
</CardContent>
</Card>
</Grid2>
+3
View File
@@ -24,3 +24,6 @@ types
# sample db
!public/sample_db.sqlite3
# test assets
test/asset
+494 -947
View File
File diff suppressed because it is too large Load Diff
+11 -1
View File
@@ -28,5 +28,15 @@ const useMockStudies = () => {
export const useMockStudy = (studyId: number | undefined) => {
const mockStudies = useMockStudies()
return mockStudies.find((study) => study.study_id === studyId)
const mockStudy = mockStudies.find((study) => study.study_id === studyId)
const mockImportance: Optuna.ParamImportance[][] = [
[
{ name: "dropout_l0", importance: 0.07990265450296263 },
{ name: "lr", importance: 0.07328545409147895 },
{ name: "n_layers", importance: 0.028260844392780343 },
{ name: "n_units_l0", importance: 0.1600821009129565 },
{ name: "optimizer", importance: 0.3296378694329876 },
],
]
return { study: mockStudy, importance: mockImportance }
}
@@ -1,5 +1,8 @@
import { CssBaseline, ThemeProvider } from "@mui/material"
import { Meta, StoryObj } from "@storybook/react"
import React from "react"
import { useMockStudy } from "../MockStudies"
import { lightTheme } from "../styles/lightTheme"
import { PlotHistory } from "./PlotHistory"
const meta: Meta<typeof PlotHistory> = {
@@ -8,14 +11,17 @@ const meta: Meta<typeof PlotHistory> = {
tags: ["autodocs"],
decorators: [
(Story, storyContext) => {
const study = useMockStudy(storyContext.parameters?.studyId)
const { study } = useMockStudy(storyContext.parameters?.studyId)
if (!study) return <p>loading...</p>
return (
<Story
args={{
study,
}}
/>
<ThemeProvider theme={lightTheme}>
<CssBaseline />
<Story
args={{
study,
}}
/>
</ThemeProvider>
)
},
],
@@ -24,7 +30,7 @@ const meta: Meta<typeof PlotHistory> = {
export default meta
type Story = StoryObj<typeof PlotHistory>
export const MockStudy1: Story = {
export const MockStudyExample1: Story = {
parameters: {
studyId: 1,
},
@@ -1,5 +1,6 @@
import { ThemeProvider } from "@mui/material"
import { CssBaseline, ThemeProvider } from "@mui/material"
import { Meta, StoryObj } from "@storybook/react"
import React from "react"
import { useMockStudy } from "../MockStudies"
import { darkTheme } from "../styles/darkTheme"
import { PlotHistory } from "./PlotHistory"
@@ -10,10 +11,11 @@ const meta: Meta<typeof PlotHistory> = {
tags: ["autodocs"],
decorators: [
(Story, storyContext) => {
const study = useMockStudy(storyContext.parameters?.studyId)
const { study } = useMockStudy(storyContext.parameters?.studyId)
if (!study) return <p>loading...</p>
return (
<ThemeProvider theme={darkTheme}>
<CssBaseline />
<Story
args={{
study,
@@ -31,7 +33,7 @@ const meta: Meta<typeof PlotHistory> = {
export default meta
type Story = StoryObj<typeof PlotHistory>
export const MockStudy1: Story = {
export const MockStudyExample1: Story = {
parameters: {
studyId: 1,
},
@@ -0,0 +1,40 @@
import { CssBaseline, ThemeProvider } from "@mui/material"
import { Meta, StoryObj } from "@storybook/react"
import React from "react"
import { useMockStudy } from "../MockStudies"
import { lightTheme } from "../styles/lightTheme"
import { PlotImportance } from "./PlotImportance"
const meta: Meta<typeof PlotImportance> = {
component: PlotImportance,
title: "PlotImportance",
tags: ["autodocs"],
decorators: [
(Story, storyContext) => {
const { study, importance } = useMockStudy(
storyContext.parameters?.studyId
)
if (!study) return <p>loading...</p>
return (
<ThemeProvider theme={lightTheme}>
<CssBaseline />
<Story
args={{
study,
importance,
}}
/>
</ThemeProvider>
)
},
],
}
export default meta
type Story = StoryObj<typeof PlotImportance>
export const MockStudyExample1: Story = {
parameters: {
studyId: 1,
},
}
@@ -1,55 +1,19 @@
import { Box, Typography, useTheme } from "@mui/material"
import { plotlyDarkTemplate } from "@optuna/react"
import init, { wasm_fanova_calculate } from "optuna"
import * as Optuna from "@optuna/types"
import * as plotly from "plotly.js-dist-min"
import React, { FC, useEffect, useState } from "react"
import { FC, useEffect } from "react"
import { plotlyDarkTemplate } from "./PlotlyDarkMode"
const plotDomId = "graph-hyperparameter-importances"
export const PlotImportance: FC<{ study: Study }> = ({ study }) => {
export const PlotImportance: FC<{
study: Optuna.Study
importance: Optuna.ParamImportance[][]
}> = ({ study, importance }) => {
const theme = useTheme()
const objectiveNames: string[] = study.directions.map(
(d, i) => `Objective ${i}`
(_d, i) => `Objective ${i}`
)
const [importance, setImportance] = useState<ParamImportance[][]>([])
useEffect(() => {
async function run_wasm() {
await init()
const x: ParamImportance[][] = study.directions.map((d, objectiveId) => {
const filteredTrials = study.trials.filter((t) =>
filterFunc(t, objectiveId)
)
if (filteredTrials.length === 0) {
return study.union_search_space.map((s) => {
return {
name: s.name,
importance: 0.5,
}
})
}
const features = study.intersection_search_space.map((s) =>
filteredTrials
.map((t) => t.params.find((p) => p.name === s.name) as TrialParam)
.map((p) => p.param_internal_value)
)
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,
importance: importance[i],
}))
})
setImportance(x)
}
run_wasm()
}, [study])
useEffect(() => {
if (importance.length > 0) {
@@ -70,22 +34,8 @@ export const PlotImportance: FC<{ study: Study }> = ({ study }) => {
)
}
const filterFunc = (trial: Trial, objectiveId: number): boolean => {
if (trial.state !== "Complete" && trial.state !== "Pruned") {
return false
}
if (trial.values === undefined) {
return false
}
return (
trial.values.length > objectiveId &&
trial.values[objectiveId] !== Infinity &&
trial.values[objectiveId] !== -Infinity
)
}
const plotParamImportancesBeta = (
importances: ParamImportance[][],
importances: Optuna.ParamImportance[][],
objectiveNames: string[],
mode: string
) => {
@@ -0,0 +1,43 @@
import { CssBaseline, ThemeProvider } from "@mui/material"
import { Meta, StoryObj } from "@storybook/react"
import React from "react"
import { useMockStudy } from "../MockStudies"
import { darkTheme } from "../styles/darkTheme"
import { PlotImportance } from "./PlotImportance"
const meta: Meta<typeof PlotImportance> = {
component: PlotImportance,
title: "PlotImportanceDark",
tags: ["autodocs"],
decorators: [
(Story, storyContext) => {
const { study, importance } = useMockStudy(
storyContext.parameters?.studyId
)
if (!study) return <p>loading...</p>
return (
<ThemeProvider theme={darkTheme}>
<CssBaseline />
<Story
args={{
study,
importance,
}}
/>
</ThemeProvider>
)
},
],
parameters: {
backgrounds: { default: "dark" },
},
}
export default meta
type Story = StoryObj<typeof PlotImportance>
export const MockStudyExample1: Story = {
parameters: {
studyId: 1,
},
}
@@ -0,0 +1,39 @@
import { CssBaseline, ThemeProvider } from "@mui/material"
import { Meta, StoryObj } from "@storybook/react"
import React from "react"
import { useMockStudy } from "../MockStudies"
import { lightTheme } from "../styles/lightTheme"
import { PlotIntermediateValues } from "./PlotIntermediateValues"
const meta: Meta<typeof PlotIntermediateValues> = {
component: PlotIntermediateValues,
title: "PlotIntermediateValues",
tags: ["autodocs"],
decorators: [
(Story, storyContext) => {
const { study } = useMockStudy(storyContext.parameters?.studyId)
if (!study) return <p>loading...</p>
return (
<ThemeProvider theme={lightTheme}>
<CssBaseline />
<Story
args={{
trials: study.trials,
includePruned: false,
logScale: false,
}}
/>
</ThemeProvider>
)
},
],
}
export default meta
type Story = StoryObj<typeof PlotIntermediateValues>
export const MockStudyExample1: Story = {
parameters: {
studyId: 1,
},
}
@@ -1,12 +1,13 @@
import { Box, Typography, useTheme } from "@mui/material"
import { plotlyDarkTemplate } from "@optuna/react"
import * as Optuna from "@optuna/types"
import * as plotly from "plotly.js-dist-min"
import React, { FC, useEffect } from "react"
import { FC, useEffect } from "react"
import { plotlyDarkTemplate } from "./PlotlyDarkMode"
const plotDomId = "graph-intermediate-values"
export const PlotIntermediateValues: FC<{
trials: Trial[]
trials: Optuna.Trial[]
includePruned: boolean
logScale: boolean
}> = ({ trials, includePruned, logScale }) => {
@@ -36,7 +37,7 @@ export const PlotIntermediateValues: FC<{
}
const plotIntermediateValue = (
trials: Trial[],
trials: Optuna.Trial[],
mode: string,
filterCompleteTrial: boolean,
filterPrunedTrial: boolean,
@@ -0,0 +1,42 @@
import { CssBaseline, ThemeProvider } from "@mui/material"
import { Meta, StoryObj } from "@storybook/react"
import React from "react"
import { useMockStudy } from "../MockStudies"
import { darkTheme } from "../styles/darkTheme"
import { PlotIntermediateValues } from "./PlotIntermediateValues"
const meta: Meta<typeof PlotIntermediateValues> = {
component: PlotIntermediateValues,
title: "PlotIntermediateValuesDark",
tags: ["autodocs"],
decorators: [
(Story, storyContext) => {
const { study } = useMockStudy(storyContext.parameters?.studyId)
if (!study) return <p>loading...</p>
return (
<ThemeProvider theme={darkTheme}>
<CssBaseline />
<Story
args={{
trials: study.trials,
includePruned: false,
logScale: false,
}}
/>
</ThemeProvider>
)
},
],
parameters: {
backgrounds: { default: "dark" },
},
}
export default meta
type Story = StoryObj<typeof PlotIntermediateValues>
export const MockStudyExample1: Story = {
parameters: {
studyId: 1,
},
}
@@ -1,5 +1,8 @@
import { CssBaseline, ThemeProvider } from "@mui/material"
import { Meta, StoryObj } from "@storybook/react"
import React from "react"
import { useMockStudy } from "../MockStudies"
import { lightTheme } from "../styles/lightTheme"
import { TrialTable } from "./TrialTable"
const meta: Meta<typeof TrialTable> = {
@@ -8,14 +11,17 @@ const meta: Meta<typeof TrialTable> = {
tags: ["autodocs"],
decorators: [
(Story, storyContext) => {
const study = useMockStudy(storyContext.parameters?.studyId)
const { study } = useMockStudy(storyContext.parameters?.studyId)
if (!study) return <p>loading...</p>
return (
<Story
args={{
study,
}}
/>
<ThemeProvider theme={lightTheme}>
<CssBaseline />
<Story
args={{
study,
}}
/>
</ThemeProvider>
)
},
],
@@ -24,7 +30,7 @@ const meta: Meta<typeof TrialTable> = {
export default meta
type Story = StoryObj<typeof TrialTable>
export const MockStudy1: Story = {
export const MockStudyExample1: Story = {
parameters: {
studyId: 1,
},
@@ -1,5 +1,6 @@
import { ThemeProvider } from "@mui/material"
import { CssBaseline, ThemeProvider } from "@mui/material"
import { Meta, StoryObj } from "@storybook/react"
import React from "react"
import { useMockStudy } from "../MockStudies"
import { darkTheme } from "../styles/darkTheme"
import { TrialTable } from "./TrialTable"
@@ -10,10 +11,11 @@ const meta: Meta<typeof TrialTable> = {
tags: ["autodocs"],
decorators: [
(Story, storyContext) => {
const study = useMockStudy(storyContext.parameters?.studyId)
const { study } = useMockStudy(storyContext.parameters?.studyId)
if (!study) return <p>loading...</p>
return (
<ThemeProvider theme={darkTheme}>
<CssBaseline />
<Story
args={{
study,
@@ -31,7 +33,7 @@ const meta: Meta<typeof TrialTable> = {
export default meta
type Story = StoryObj<typeof TrialTable>
export const MockStudy1: Story = {
export const MockStudyExample1: Story = {
parameters: {
studyId: 1,
},
+4 -2
View File
@@ -1,5 +1,7 @@
export { DataGrid } from "./components/DataGrid"
export type { DataGridColumn } from "./components/DataGrid"
export { PlotHistory } from "./components/PlotHistory"
export { TrialTable } from "./components/TrialTable"
export { plotlyDarkTemplate } from "./components/PlotlyDarkMode"
export { PlotHistory } from "./components/PlotHistory"
export { PlotImportance } from "./components/PlotImportance"
export { PlotIntermediateValues } from "./components/PlotIntermediateValues"
export { TrialTable } from "./components/TrialTable"
+4
View File
@@ -1,7 +1,11 @@
import { createTheme } from "@mui/material"
import blue from "@mui/material/colors/blue"
import pink from "@mui/material/colors/pink"
export const darkTheme = createTheme({
palette: {
mode: "dark",
primary: blue,
secondary: pink,
},
})
+11
View File
@@ -0,0 +1,11 @@
import { createTheme } from "@mui/material"
import blue from "@mui/material/colors/blue"
import pink from "@mui/material/colors/pink"
export const lightTheme = createTheme({
palette: {
mode: "light",
primary: blue,
secondary: pink,
},
})
+44
View File
@@ -0,0 +1,44 @@
import * as Optuna from "@optuna/types"
import { render, screen } from "@testing-library/react"
import React from "react"
import { describe, expect, test } from "vitest"
import { PlotImportance } from "../src/components/PlotImportance"
describe("PlotImportance Tests", async () => {
const setup = ({
study,
importance,
dataTestId,
}: {
study: Optuna.Study
importance: Optuna.ParamImportance[][]
dataTestId: string
}) => {
const Wrapper = ({
dataTestId,
children,
}: {
dataTestId: string
children: React.ReactNode
}) => <div data-testid={dataTestId}>{children}</div>
return render(
<Wrapper dataTestId={dataTestId}>
<PlotImportance study={study} importance={importance} />
</Wrapper>
)
}
for (const study of window.mockStudies) {
test(`PlotImportance (study name: ${study.study_name})`, () => {
const importance = window.mockImportances[study.study_name] ?? []
setup({
study,
importance,
dataTestId: `plot-importance-${study.study_id}`,
})
expect(
screen.getByTestId(`plot-importance-${study.study_id}`)
).toBeInTheDocument()
})
}
})
@@ -0,0 +1,38 @@
import * as Optuna from "@optuna/types"
import { render, screen } from "@testing-library/react"
import React from "react"
import { describe, expect, test } from "vitest"
import { PlotIntermediateValues } from "../src/components/PlotIntermediateValues"
describe("PlotIntermediateValues Tests", async () => {
const setup = ({
study,
dataTestId,
}: { study: Optuna.Study; dataTestId: string }) => {
const Wrapper = ({
dataTestId,
children,
}: {
dataTestId: string
children: React.ReactNode
}) => <div data-testid={dataTestId}>{children}</div>
return render(
<Wrapper dataTestId={dataTestId}>
<PlotIntermediateValues
trials={study.trials}
includePruned={false}
logScale={false}
/>
</Wrapper>
)
}
for (const study of window.mockStudies) {
test(`PlotIntermediateValues (study name: ${study.study_name})`, () => {
setup({ study, dataTestId: `plot-intermediatevalues-${study.study_id}` })
expect(
screen.getByTestId(`plot-intermediatevalues-${study.study_id}`)
).toBeInTheDocument()
})
}
})
+139 -2
View File
@@ -1,3 +1,4 @@
import json
import logging
import math
import os.path
@@ -7,6 +8,8 @@ from typing import Tuple
import optuna
from optuna.distributions import CategoricalDistribution
from optuna.distributions import FloatDistribution
from optuna.importance import get_param_importances
from optuna.importance import PedAnovaImportanceEvaluator
from optuna.storages import BaseStorage
from optuna.storages import JournalFileStorage
from optuna.storages import JournalStorage
@@ -22,7 +25,9 @@ def remove_assets() -> None:
os.mkdir(BASE_DIR)
def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStorage:
def create_optuna_storage(
storage: BaseStorage, params_importances: dict[str, list[dict[str, float]]]
) -> optuna.storages.InMemoryStorage:
# Single-objective study
study = optuna.create_study(
study_name="single-objective", storage=storage, sampler=optuna.samplers.RandomSampler()
@@ -35,6 +40,14 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
return (x1 - 2) ** 2 + (x2 - 5) ** 2
study.optimize(objective_single, n_trials=100)
params_importances[study.study_name] = [
get_param_importances(
study,
target=lambda trial: trial.values[objective_id],
evaluator=PedAnovaImportanceEvaluator(),
)
for objective_id in range(len(study.directions))
]
# Single-objective study with dynamic search space
study = optuna.create_study(
@@ -49,6 +62,14 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
return -((trial.suggest_float("x2", -10, 0) + 5) ** 2)
study.optimize(objective_single_dynamic, n_trials=50)
params_importances[study.study_name] = [
get_param_importances(
study,
target=lambda trial: trial.values[objective_id],
evaluator=PedAnovaImportanceEvaluator(),
)
for objective_id in range(len(study.directions))
]
study = optuna.create_study(
study_name="check-rank-plot", storage=storage, sampler=optuna.samplers.RandomSampler()
@@ -64,6 +85,14 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
return (x1 - 2) ** 2 + (x2 - 5) ** 2
study.optimize(objective_single, n_trials=1000)
params_importances[study.study_name] = [
get_param_importances(
study,
target=lambda trial: trial.values[objective_id],
evaluator=PedAnovaImportanceEvaluator(),
)
for objective_id in range(len(study.directions))
]
# Single-objective study
study = optuna.create_study(study_name="single-objective-user-attrs", storage=storage)
@@ -79,6 +108,14 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
return (x1 - 2) ** 2 + (x2 - 5) ** 2
study.optimize(objective_single_user_attr, n_trials=100)
params_importances[study.study_name] = [
get_param_importances(
study,
target=lambda trial: trial.values[objective_id],
evaluator=PedAnovaImportanceEvaluator(),
)
for objective_id in range(len(study.directions))
]
# Single objective study with 'inf', '-inf', or 'nan' value
study = optuna.create_study(study_name="single-inf", storage=storage)
@@ -93,6 +130,14 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
return x**2
study.optimize(objective_single_inf, n_trials=50)
params_importances[study.study_name] = [
get_param_importances(
study,
target=lambda trial: trial.values[objective_id],
evaluator=PedAnovaImportanceEvaluator(),
)
for objective_id in range(len(study.directions))
]
# Single objective pruned after reported 'inf', '-inf', or 'nan'
study = optuna.create_study(study_name="single-inf-report", storage=storage)
@@ -112,6 +157,14 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
return x**2
study.optimize(objective_single_inf_report, n_trials=50)
params_importances[study.study_name] = [
get_param_importances(
study,
target=lambda trial: trial.values[objective_id],
evaluator=PedAnovaImportanceEvaluator(),
)
for objective_id in range(len(study.directions))
]
# Single objective with reported nan value
study = optuna.create_study(study_name="single-nan-report", storage=storage)
@@ -124,6 +177,14 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
return (x1 - 2) ** 2 + (x2 - 5) ** 2
study.optimize(objective_single_nan_report, n_trials=100)
params_importances[study.study_name] = [
get_param_importances(
study,
target=lambda trial: trial.values[objective_id],
evaluator=PedAnovaImportanceEvaluator(),
)
for objective_id in range(len(study.directions))
]
# Single-objective study with 1 parameter
study = optuna.create_study(
@@ -135,6 +196,14 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
return -((x1 - 2) ** 2)
study.optimize(objective_single_with_1param, n_trials=50)
params_importances[study.study_name] = [
get_param_importances(
study,
target=lambda trial: trial.values[objective_id],
evaluator=PedAnovaImportanceEvaluator(),
)
for objective_id in range(len(study.directions))
]
# Single-objective study with 1 parameter
study = optuna.create_study(study_name="long-parameter-names", storage=storage)
@@ -149,6 +218,14 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
return (x1 - 2) ** 2 + (x2 - 5) ** 2
study.optimize(objective_long_parameter_names, n_trials=50)
params_importances[study.study_name] = [
get_param_importances(
study,
target=lambda trial: trial.values[objective_id],
evaluator=PedAnovaImportanceEvaluator(),
)
for objective_id in range(len(study.directions))
]
# Multi-objective study
study = optuna.create_study(
@@ -166,6 +243,14 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
return v0, v1
study.optimize(objective_multi, n_trials=50)
params_importances[study.study_name] = [
get_param_importances(
study,
target=lambda trial: trial.values[objective_id],
evaluator=PedAnovaImportanceEvaluator(),
)
for objective_id in range(len(study.directions))
]
# Multi-objective study with dynamic search space
study = optuna.create_study(
@@ -188,6 +273,14 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
return v0, v1
study.optimize(objective_multi_dynamic, n_trials=50)
params_importances[study.study_name] = [
get_param_importances(
study,
target=lambda trial: trial.values[objective_id],
evaluator=PedAnovaImportanceEvaluator(),
)
for objective_id in range(len(study.directions))
]
# Pruning with no intermediate values
study = optuna.create_study(study_name="binh-korn-function-with-constraints", storage=storage)
@@ -201,6 +294,14 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
return v
study.optimize(objective_prune_with_no_trials, n_trials=100)
params_importances[study.study_name] = [
get_param_importances(
study,
target=lambda trial: trial.values[objective_id],
evaluator=PedAnovaImportanceEvaluator(),
)
for objective_id in range(len(study.directions))
]
# With failed trials
study = optuna.create_study(study_name="failed trials", storage=storage)
@@ -214,6 +315,14 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
return v
study.optimize(objective_sometimes_got_failed, n_trials=100, catch=(Exception,))
params_importances[study.study_name] = [
get_param_importances(
study,
target=lambda trial: trial.values[objective_id],
evaluator=PedAnovaImportanceEvaluator(),
)
for objective_id in range(len(study.directions))
]
# No trials single-objective study
study = optuna.create_study(study_name="no trials single-objective study", storage=storage)
@@ -251,6 +360,14 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
return v0
study.optimize(objective_constraints, n_trials=100)
params_importances[study.study_name] = [
get_param_importances(
study,
target=lambda trial: trial.values[objective_id],
evaluator=PedAnovaImportanceEvaluator(),
)
for objective_id in range(len(study.directions))
]
# Study with Running Trials
study = optuna.create_study(
@@ -284,6 +401,14 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
return 0.0
study.optimize(objective_intermediate_values, n_trials=10)
params_importances[study.study_name] = [
get_param_importances(
study,
target=lambda trial: trial.values[objective_id],
evaluator=PedAnovaImportanceEvaluator(),
)
for objective_id in range(len(study.directions))
]
trial = study.ask(
{"x": FloatDistribution(0, 10), "y": CategoricalDistribution(["Foo", "Bar"])}
) # To create a running trial
@@ -308,6 +433,14 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
return 0.0
study.optimize(objective_intermediate_values_constraints, n_trials=10)
params_importances[study.study_name] = [
get_param_importances(
study,
target=lambda trial: trial.values[objective_id],
evaluator=PedAnovaImportanceEvaluator(),
)
for objective_id in range(len(study.directions))
]
trial = study.ask(
{"x": FloatDistribution(0, 10), "y": CategoricalDistribution(["Foo", "Bar"])}
) # To create a running trial
@@ -318,7 +451,11 @@ def create_optuna_storage(storage: BaseStorage) -> optuna.storages.InMemoryStora
def main() -> None:
remove_assets()
storage = JournalStorage(JournalFileStorage(os.path.join(BASE_DIR, "journal.log")))
create_optuna_storage(storage)
params_importances: dict[str, dict[str, float]] = {}
create_optuna_storage(storage, params_importances)
with open(os.path.join(BASE_DIR, "params_importances.json"), "w") as f:
json.dump(params_importances, f, indent=2)
if __name__ == "__main__":
+21 -4
View File
@@ -5,14 +5,15 @@ import { loadStorageFromFile } from "../src/utils/loadStorageFromFile"
declare global {
interface Window {
mockStudies: Optuna.Study[]
mockImportances: Record<string, Optuna.ParamImportance[][]>
}
}
const data = fs.readFileSync("./test/asset/journal.log")
const blob = new Blob([data])
const file = new File([blob], "journal.log")
const journalData = fs.readFileSync("./test/asset/journal.log")
const journalBlob = new Blob([journalData])
const journalFile = new File([journalBlob], "journal.log")
const mockStudies: Optuna.Study[] = []
await loadStorageFromFile(file, (value) => {
await loadStorageFromFile(journalFile, (value) => {
if (Array.isArray(value)) {
mockStudies.push(...value)
} else {
@@ -21,6 +22,22 @@ await loadStorageFromFile(file, (value) => {
})
window.mockStudies = mockStudies
const importancesData = fs.readFileSync("./test/asset/params_importances.json")
const importancesJson = JSON.parse(importancesData.toString())
const mockImportances: Record<string, Optuna.ParamImportance[][]> = {}
for (const key in importancesJson) {
mockImportances[key] = importancesJson[key].map(
(importance: Record<string, number>) => {
const importanceArray: Optuna.ParamImportance[] = []
for (const name in importance) {
importanceArray.push({ name, importance: importance[name] })
}
return importanceArray
}
)
}
window.mockImportances = mockImportances
// mock window.URL.createObjectURL in JSDOM
window.HTMLCanvasElement.prototype.getContext = () => null
window.URL.createObjectURL = () => ""