mirror of
https://github.com/wassname/optuna-dashboard.git
synced 2026-09-10 12:23:22 +08:00
Add API to set objective names
This commit is contained in:
@@ -88,14 +88,18 @@ This function uses wsgiref module which is not intended for the production use.
|
||||
This function exposes WSGI interface for people who want to run on the
|
||||
production-class WSGI servers like Gunicorn or uWSGI.
|
||||
|
||||
**`save_study_note(study: Study, body: string) -> None`**
|
||||
**`save_study_note(study: Study, body: str) -> None`**
|
||||
|
||||
Save the note (Markdown format) to the Study.
|
||||
|
||||
**`save_trial_note(trial: Trial, body: string) -> None`**
|
||||
**`save_trial_note(trial: Trial, body: str) -> None`**
|
||||
|
||||
Save the note (Markdown format) to the Trial.
|
||||
|
||||
**`set_objective_names(study: Study, names: list[str]) -> None`**
|
||||
|
||||
Set the names of objectives.
|
||||
|
||||
</details>
|
||||
|
||||
## Using an official Docker image
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from ._app import run_server # noqa
|
||||
from ._app import wsgi # noqa
|
||||
from ._named_objectives import set_objective_names # noqa
|
||||
from ._note import save_study_note # noqa
|
||||
from ._note import save_trial_note # noqa
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
from typing import Optional
|
||||
|
||||
import optuna
|
||||
|
||||
|
||||
SYSTEM_ATTR_NAME = "dashboard:objective_names"
|
||||
|
||||
|
||||
def set_objective_names(study: optuna.Study, names: list[str]) -> None:
|
||||
"""Set the names of objectives.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import optuna
|
||||
from optuna_dashboard import set_objective_names
|
||||
|
||||
study = optuna.create_study(directions=["minimize", "minimize"])
|
||||
set_objective_names(study, ["val_loss", "flops"])
|
||||
"""
|
||||
storage = study._storage
|
||||
study_id = study._study_id
|
||||
|
||||
directions = storage.get_study_directions(study_id)
|
||||
if len(directions) != len(names):
|
||||
raise ValueError("names must be the same length with the number of objectives.")
|
||||
storage.set_study_system_attr(study_id, SYSTEM_ATTR_NAME, names)
|
||||
|
||||
|
||||
def get_objective_names(system_attrs: dict[str, Any]) -> Optional[list[str]]:
|
||||
return system_attrs.get(SYSTEM_ATTR_NAME)
|
||||
@@ -11,6 +11,7 @@ from optuna.study import StudySummary
|
||||
from optuna.trial import FrozenTrial
|
||||
|
||||
from . import _note as note
|
||||
from ._named_objectives import get_objective_names
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -99,6 +100,9 @@ def serialize_study_detail(
|
||||
serialized["union_user_attrs"] = [{"key": a[0], "sortable": a[1]} for a in union_user_attrs]
|
||||
serialized["has_intermediate_values"] = has_intermediate_values
|
||||
serialized["note"] = note.get_note_from_system_attrs(system_attrs, None)
|
||||
objective_names = get_objective_names(system_attrs)
|
||||
if objective_names:
|
||||
serialized["objective_names"] = objective_names
|
||||
return serialized
|
||||
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ interface StudyDetailResponse {
|
||||
union_user_attrs: AttributeSpec[]
|
||||
has_intermediate_values: boolean
|
||||
note: Note
|
||||
objective_names?: string[]
|
||||
}
|
||||
|
||||
export const getStudyDetailAPI = (
|
||||
@@ -80,6 +81,7 @@ export const getStudyDetailAPI = (
|
||||
union_user_attrs: res.data.union_user_attrs,
|
||||
has_intermediate_values: res.data.has_intermediate_values,
|
||||
note: res.data.note,
|
||||
objective_names: res.data.objective_names,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ export const Contour: FC<{
|
||||
const [xParam, setXParam] = useState("")
|
||||
const [yParam, setYParam] = useState("")
|
||||
const paramNames = study?.union_search_space.map((s) => s.name)
|
||||
const objectiveNames: string[] = study?.objective_names || []
|
||||
|
||||
if (!xParam && paramNames && paramNames.length > 0) {
|
||||
setXParam(paramNames[0])
|
||||
@@ -85,7 +86,7 @@ export const Contour: FC<{
|
||||
<Select value={objectiveId} onChange={handleObjectiveChange}>
|
||||
{study.directions.map((d, i) => (
|
||||
<MenuItem value={i} key={i}>
|
||||
{i}
|
||||
{objectiveNames.length === study?.directions.length ? objectiveNames[i] : `${i}`}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
|
||||
@@ -20,6 +20,7 @@ export const Edf: FC<{
|
||||
}> = ({ study = null }) => {
|
||||
const theme = useTheme()
|
||||
const [objectiveId, setObjectiveId] = useState<number>(0)
|
||||
const objectiveNames: string[] = study?.objective_names || []
|
||||
|
||||
const handleObjectiveChange = (event: SelectChangeEvent<number>) => {
|
||||
setObjectiveId(event.target.value as number)
|
||||
@@ -48,7 +49,7 @@ export const Edf: FC<{
|
||||
<Select value={objectiveId} onChange={handleObjectiveChange}>
|
||||
{study.directions.map((d, i) => (
|
||||
<MenuItem value={i} key={i}>
|
||||
{i}
|
||||
{objectiveNames.length === study?.directions.length ? objectiveNames[i] : `${i}`}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
|
||||
@@ -28,6 +28,7 @@ export const GraphHistory: FC<{
|
||||
const [logScale, setLogScale] = useState<boolean>(false)
|
||||
const [filterCompleteTrial, setFilterCompleteTrial] = useState<boolean>(false)
|
||||
const [filterPrunedTrial, setFilterPrunedTrial] = useState<boolean>(false)
|
||||
const objectiveNames: string[] = study?.objective_names || []
|
||||
|
||||
const handleObjectiveChange = (event: SelectChangeEvent<number>) => {
|
||||
setObjectiveId(event.target.value as number)
|
||||
@@ -92,7 +93,7 @@ export const GraphHistory: FC<{
|
||||
<Select value={objectiveId} onChange={handleObjectiveChange}>
|
||||
{study.directions.map((d, i) => (
|
||||
<MenuItem value={i} key={i}>
|
||||
{i}
|
||||
{objectiveNames.length === study?.directions.length ? objectiveNames[i] : `${i}`}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
|
||||
@@ -32,6 +32,7 @@ export const GraphHyperparameterImportanceBeta: FC<{
|
||||
const numCompletedTrials =
|
||||
study?.trials.filter((t) => t.state === "Complete").length || 0
|
||||
const nObjectives = useStudyDirections(studyId)?.length
|
||||
const objectiveNames: string[] = study?.objective_names || []
|
||||
|
||||
useEffect(() => {
|
||||
action.updateParamImportance(studyId)
|
||||
@@ -48,7 +49,11 @@ export const GraphHyperparameterImportanceBeta: FC<{
|
||||
{Array.from({ length: nObjectives || 1 }, (_, i) => {
|
||||
let title = `Importance for the Objective Value`
|
||||
if (nObjectives != null && nObjectives > 1) {
|
||||
title = `Importance for the Objective ${i}`
|
||||
if (objectiveNames.length == nObjectives) {
|
||||
title = `Importance for ${objectiveNames[i]} (Objective ${i})`
|
||||
} else {
|
||||
title = `Importance for the Objective ${i}`
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Grid2 key={i} xs={6}>
|
||||
|
||||
@@ -20,6 +20,7 @@ export const GraphParallelCoordinate: FC<{
|
||||
}> = ({ study = null }) => {
|
||||
const theme = useTheme()
|
||||
const [objectiveId, setObjectiveId] = useState<number>(0)
|
||||
const objectiveNames: string[] = study?.objective_names || []
|
||||
|
||||
const handleObjectiveChange = (event: SelectChangeEvent<number>) => {
|
||||
setObjectiveId(event.target.value as number)
|
||||
@@ -49,7 +50,7 @@ export const GraphParallelCoordinate: FC<{
|
||||
<Select value={objectiveId} onChange={handleObjectiveChange}>
|
||||
{study.directions.map((d, i) => (
|
||||
<MenuItem value={i} key={i}>
|
||||
{i}
|
||||
{objectiveNames.length === study?.directions.length ? objectiveNames[i] : `${i}`}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
|
||||
@@ -21,6 +21,7 @@ export const GraphParetoFront: FC<{
|
||||
const theme = useTheme()
|
||||
const [objectiveXId, setObjectiveXId] = useState<number>(0)
|
||||
const [objectiveYId, setObjectiveYId] = useState<number>(1)
|
||||
const objectiveNames: string[] = study?.objective_names || []
|
||||
|
||||
const handleObjectiveXChange = (event: SelectChangeEvent<number>) => {
|
||||
setObjectiveXId(event.target.value as number)
|
||||
@@ -55,7 +56,7 @@ export const GraphParetoFront: FC<{
|
||||
<Select value={objectiveXId} onChange={handleObjectiveXChange}>
|
||||
{study.directions.map((d, i) => (
|
||||
<MenuItem value={i} key={i}>
|
||||
{i}
|
||||
{objectiveNames.length === study?.directions.length ? objectiveNames[i] : `${i}`}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
@@ -65,7 +66,7 @@ export const GraphParetoFront: FC<{
|
||||
<Select value={objectiveYId} onChange={handleObjectiveYChange}>
|
||||
{study.directions.map((d, i) => (
|
||||
<MenuItem value={i} key={i}>
|
||||
{i}
|
||||
{objectiveNames.length === study?.directions.length ? objectiveNames[i] : `${i}`}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
|
||||
@@ -32,6 +32,7 @@ export const GraphSlice: FC<{
|
||||
const distributions = new Map(
|
||||
study?.union_search_space.map((s) => [s.name, s.distribution])
|
||||
)
|
||||
const objectiveNames: string[] = study?.objective_names || []
|
||||
if (selected === null && paramNames && paramNames.length > 0) {
|
||||
const distribution = distributions.get(paramNames[0]) || ""
|
||||
setSelected(paramNames[0])
|
||||
@@ -82,7 +83,7 @@ export const GraphSlice: FC<{
|
||||
<Select value={objectiveId} onChange={handleObjectiveChange}>
|
||||
{study.directions.map((d, i) => (
|
||||
<MenuItem value={i} key={i}>
|
||||
{i}
|
||||
{objectiveNames.length === study?.directions.length ? objectiveNames[i] : `${i}`}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
@@ -93,7 +94,7 @@ export const GraphSlice: FC<{
|
||||
<Select value={selected || ""} onChange={handleSelectedParam}>
|
||||
{paramNames?.map((p, i) => (
|
||||
<MenuItem value={p} key={i}>
|
||||
{p}
|
||||
{objectiveNames.length === study?.directions.length ? objectiveNames[i] : `${i}`}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
|
||||
@@ -8,6 +8,7 @@ export const TrialTable: FC<{
|
||||
initialRowsPerPage?: number
|
||||
}> = ({ studyDetail, initialRowsPerPage }) => {
|
||||
const trials: Trial[] = studyDetail !== null ? studyDetail.trials : []
|
||||
const objectiveNames: string[] = studyDetail?.objective_names || []
|
||||
|
||||
const columns: DataGridColumn<Trial>[] = [
|
||||
{ field: "number", label: "Number", sortable: true, padding: "none" },
|
||||
@@ -55,7 +56,7 @@ export const TrialTable: FC<{
|
||||
const objectiveColumns: DataGridColumn<Trial>[] =
|
||||
studyDetail.directions.map((s, objectiveId) => ({
|
||||
field: "values",
|
||||
label: `Objective ${objectiveId}`,
|
||||
label: objectiveNames.length === studyDetail?.directions.length ? objectiveNames[objectiveId] : `Objective ${objectiveId}`,
|
||||
sortable: true,
|
||||
less: (firstEl, secondEl): number => {
|
||||
const firstVal = firstEl.values?.[objectiveId]
|
||||
|
||||
Vendored
+1
@@ -106,6 +106,7 @@ declare interface StudyDetail {
|
||||
union_user_attrs: AttributeSpec[]
|
||||
has_intermediate_values: boolean
|
||||
note: Note
|
||||
objective_names?: string[]
|
||||
}
|
||||
|
||||
declare interface StudyDetails {
|
||||
|
||||
Reference in New Issue
Block a user