mirror of
https://github.com/wassname/optuna-dashboard.git
synced 2026-09-22 13:20:38 +08:00
Support Optuna v2.4.0
This commit is contained in:
@@ -140,10 +140,12 @@ def create_app(storage_or_url: Union[str, BaseStorage]) -> Bottle:
|
||||
except DuplicatedStudyError:
|
||||
response.status = 400 # Bad request
|
||||
return {"reason": f"'{study_name}' is already exists"}
|
||||
|
||||
# TODO(c-bata): Support multi-objective study.
|
||||
if direction.lower() == "maximize":
|
||||
storage.set_study_direction(study_id, StudyDirection.MAXIMIZE)
|
||||
storage.set_study_directions(study_id, [StudyDirection.MAXIMIZE])
|
||||
else:
|
||||
storage.set_study_direction(study_id, StudyDirection.MINIMIZE)
|
||||
storage.set_study_directions(study_id, [StudyDirection.MINIMIZE])
|
||||
|
||||
summary = get_study_summary(storage, study_id)
|
||||
if summary is None:
|
||||
|
||||
@@ -49,7 +49,7 @@ def serialize_study_summary(summary: StudySummary) -> Dict[str, Any]:
|
||||
serialized = {
|
||||
"study_id": summary._study_id,
|
||||
"study_name": summary.study_name,
|
||||
"direction": summary.direction.name.lower(),
|
||||
"directions": [d.name.lower() for d in summary.directions],
|
||||
"user_attrs": serialize_attrs(summary.user_attrs),
|
||||
"system_attrs": serialize_attrs(summary.system_attrs),
|
||||
}
|
||||
@@ -70,7 +70,7 @@ def serialize_study_detail(
|
||||
) -> Dict[str, Any]:
|
||||
serialized: Dict[str, Any] = {
|
||||
"name": summary.study_name,
|
||||
"direction": summary.direction.name.lower(),
|
||||
"directions": [d.name.lower() for d in summary.directions],
|
||||
}
|
||||
if summary.datetime_start is not None:
|
||||
serialized["datetime_start"] = summary.datetime_start.isoformat()
|
||||
@@ -98,8 +98,8 @@ def serialize_frozen_trial(study_id: int, trial: FrozenTrial) -> Dict[str, Any]:
|
||||
"system_attrs": serialize_attrs(trial.system_attrs),
|
||||
}
|
||||
|
||||
if trial.value is not None:
|
||||
serialized["value"] = trial.value
|
||||
if trial.values is not None:
|
||||
serialized["values"] = trial.values
|
||||
|
||||
if trial.datetime_start is not None:
|
||||
serialized["datetime_start"] = trial.datetime_start.isoformat()
|
||||
|
||||
@@ -7,7 +7,7 @@ interface TrialResponse {
|
||||
study_id: number
|
||||
number: number
|
||||
state: TrialState
|
||||
value?: number
|
||||
values?: number[]
|
||||
intermediate_values: TrialIntermediateValue[]
|
||||
datetime_start: string
|
||||
datetime_complete?: string
|
||||
@@ -22,7 +22,7 @@ const convertTrialResponse = (res: TrialResponse): Trial => {
|
||||
study_id: res.study_id,
|
||||
number: res.number,
|
||||
state: res.state,
|
||||
value: res.value,
|
||||
values: res.values,
|
||||
intermediate_values: res.intermediate_values,
|
||||
datetime_start: new Date(res.datetime_start),
|
||||
datetime_complete: res.datetime_complete
|
||||
@@ -37,7 +37,7 @@ const convertTrialResponse = (res: TrialResponse): Trial => {
|
||||
interface StudyDetailResponse {
|
||||
name: string
|
||||
datetime_start: string
|
||||
direction: StudyDirection
|
||||
directions: StudyDirection[]
|
||||
best_trial?: TrialResponse
|
||||
trials: TrialResponse[]
|
||||
}
|
||||
@@ -54,7 +54,7 @@ export const getStudyDetailAPI = (studyId: number): Promise<StudyDetail> => {
|
||||
return {
|
||||
name: res.data.name,
|
||||
datetime_start: new Date(res.data.datetime_start),
|
||||
direction: res.data.direction,
|
||||
directions: res.data.directions,
|
||||
best_trial: res.data.best_trial
|
||||
? convertTrialResponse(res.data.best_trial)
|
||||
: undefined,
|
||||
@@ -67,7 +67,7 @@ interface StudySummariesResponse {
|
||||
study_summaries: {
|
||||
study_id: number
|
||||
study_name: string
|
||||
direction: StudyDirection
|
||||
directions: StudyDirection[]
|
||||
best_trial?: {
|
||||
trial_id: number
|
||||
study_id: number
|
||||
@@ -99,7 +99,7 @@ export const getStudySummariesAPI = (): Promise<StudySummary[]> => {
|
||||
return {
|
||||
study_id: study.study_id,
|
||||
study_name: study.study_name,
|
||||
direction: study.direction,
|
||||
directions: study.directions,
|
||||
best_trial: best_trial,
|
||||
user_attrs: study.user_attrs,
|
||||
system_attrs: study.system_attrs,
|
||||
@@ -116,7 +116,7 @@ interface CreateNewStudyResponse {
|
||||
study_summary: {
|
||||
study_id: number
|
||||
study_name: string
|
||||
direction: StudyDirection
|
||||
directions: StudyDirection[]
|
||||
best_trial?: {
|
||||
trial_id: number
|
||||
study_id: number
|
||||
@@ -150,7 +150,7 @@ export const createNewStudyAPI = (
|
||||
return {
|
||||
study_id: study_summary.study_id,
|
||||
study_name: study_summary.study_name,
|
||||
direction: study_summary.direction,
|
||||
directions: study_summary.directions,
|
||||
// best_trial: undefined,
|
||||
user_attrs: study_summary.user_attrs,
|
||||
system_attrs: study_summary.system_attrs,
|
||||
|
||||
@@ -44,6 +44,7 @@ export const GraphHistory: FC<{
|
||||
if (study !== null) {
|
||||
plotHistory(
|
||||
study,
|
||||
0, // TODO(c-bata): Support multi-objective studies.
|
||||
xAxis,
|
||||
logScale,
|
||||
filterCompleteTrial,
|
||||
@@ -121,6 +122,7 @@ export const GraphHistory: FC<{
|
||||
|
||||
const plotHistory = (
|
||||
study: StudyDetail,
|
||||
objectiveId: number,
|
||||
xAxis: string,
|
||||
logScale: boolean,
|
||||
filterCompleteTrial: boolean,
|
||||
@@ -163,13 +165,19 @@ const plotHistory = (
|
||||
let currentBest: number | null = null
|
||||
filteredTrials.forEach((item) => {
|
||||
if (currentBest === null) {
|
||||
currentBest = item.value!
|
||||
currentBest = item.values![objectiveId]
|
||||
trialsForLinePlot.push(item)
|
||||
} else if (study.direction === "maximize" && item.value! > currentBest) {
|
||||
currentBest = item.value!
|
||||
} else if (
|
||||
study.directions[objectiveId] === "maximize" &&
|
||||
item.values![objectiveId] > currentBest
|
||||
) {
|
||||
currentBest = item.values![objectiveId]
|
||||
trialsForLinePlot.push(item)
|
||||
} else if (study.direction === "minimize" && item.value! < currentBest) {
|
||||
currentBest = item.value!
|
||||
} else if (
|
||||
study.directions[objectiveId] === "minimize" &&
|
||||
item.values![objectiveId] < currentBest
|
||||
) {
|
||||
currentBest = item.values![objectiveId]
|
||||
trialsForLinePlot.push(item)
|
||||
}
|
||||
})
|
||||
@@ -184,13 +192,15 @@ const plotHistory = (
|
||||
|
||||
let xForLinePlot = trialsForLinePlot.map(getAxisX)
|
||||
xForLinePlot.push(getAxisX(filteredTrials[filteredTrials.length - 1]))
|
||||
let yForLinePlot = trialsForLinePlot.map((t: Trial): number => t.value!)
|
||||
let yForLinePlot = trialsForLinePlot.map(
|
||||
(t: Trial): number => t.values![objectiveId]
|
||||
)
|
||||
yForLinePlot.push(yForLinePlot[yForLinePlot.length - 1])
|
||||
|
||||
const plotData: Partial<plotly.PlotData>[] = [
|
||||
{
|
||||
x: filteredTrials.map(getAxisX),
|
||||
y: filteredTrials.map((t: Trial): number => t.value!),
|
||||
y: filteredTrials.map((t: Trial): number => t.values![objectiveId]),
|
||||
mode: "markers",
|
||||
type: "scatter",
|
||||
},
|
||||
|
||||
@@ -7,12 +7,12 @@ export const GraphParallelCoordinate: FC<{
|
||||
trials: Trial[]
|
||||
}> = ({ trials = [] }) => {
|
||||
useEffect(() => {
|
||||
plotCoordinate(trials)
|
||||
plotCoordinate(trials, 0) // TODO(c-bata): Support multi-objective studies.
|
||||
}, [trials])
|
||||
return <div id={plotDomId} />
|
||||
}
|
||||
|
||||
const plotCoordinate = (trials: Trial[]) => {
|
||||
const plotCoordinate = (trials: Trial[], objectiveId: number) => {
|
||||
if (document.getElementById(plotDomId) === null) {
|
||||
return
|
||||
}
|
||||
@@ -47,7 +47,9 @@ const plotCoordinate = (trials: Trial[]) => {
|
||||
return
|
||||
}
|
||||
|
||||
const objectiveValues: number[] = filteredTrials.map((t) => t.value!)
|
||||
const objectiveValues: number[] = filteredTrials.map(
|
||||
(t) => t.values![objectiveId]
|
||||
)
|
||||
let dimensions = [
|
||||
{
|
||||
label: "Objective value",
|
||||
|
||||
@@ -42,6 +42,10 @@ interface ParamTypes {
|
||||
studyId: string
|
||||
}
|
||||
|
||||
const isSingleObjectiveStudy = (studyDetail: StudyDetail): boolean => {
|
||||
return studyDetail.directions.length === 1
|
||||
}
|
||||
|
||||
export const useStudyDetail = (
|
||||
action: Action,
|
||||
studyId: number
|
||||
@@ -93,27 +97,31 @@ export const StudyDetail: FC<{}> = () => {
|
||||
<Paper className={classes.paper}>
|
||||
<Typography variant="h6">{title}</Typography>
|
||||
</Paper>
|
||||
<Card className={classes.card}>
|
||||
<CardContent>
|
||||
<GraphHistory study={studyDetail} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Grid container direction="row">
|
||||
<Grid item xs={6}>
|
||||
{studyDetail !== null && isSingleObjectiveStudy(studyDetail) ? (
|
||||
<div>
|
||||
<Card className={classes.card}>
|
||||
<CardContent>
|
||||
<GraphParallelCoordinate trials={trials} />
|
||||
<GraphHistory study={studyDetail} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Card className={classes.card}>
|
||||
<CardContent>
|
||||
<GraphIntermediateValues trials={trials} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container direction="row">
|
||||
<Grid item xs={6}>
|
||||
<Card className={classes.card}>
|
||||
<CardContent>
|
||||
<GraphParallelCoordinate trials={trials} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Card className={classes.card}>
|
||||
<CardContent>
|
||||
<GraphIntermediateValues trials={trials} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>
|
||||
) : null}
|
||||
<Card className={classes.card}>
|
||||
<TrialTable trials={trials} />
|
||||
</Card>
|
||||
@@ -134,7 +142,12 @@ const TrialTable: FC<{ trials: Trial[] }> = ({ trials = [] }) => {
|
||||
padding: "none",
|
||||
toCellValue: (i) => trials[i].state.toString(),
|
||||
},
|
||||
{ field: "value", label: "Value", sortable: true },
|
||||
{
|
||||
field: "values",
|
||||
label: "Value",
|
||||
sortable: true,
|
||||
toCellValue: (i) => trials[i].values?.join() || null,
|
||||
},
|
||||
{
|
||||
field: "params",
|
||||
label: "Params",
|
||||
|
||||
@@ -76,16 +76,21 @@ export const StudyList: FC<{}> = () => {
|
||||
),
|
||||
},
|
||||
{
|
||||
field: "direction",
|
||||
field: "directions",
|
||||
label: "Direction",
|
||||
sortable: false,
|
||||
toCellValue: (i) => studies[i].direction.toString(),
|
||||
toCellValue: (i) => studies[i].directions.join(),
|
||||
},
|
||||
{
|
||||
field: "best_trial",
|
||||
label: "Best value",
|
||||
sortable: false,
|
||||
toCellValue: (i) => studies[i].best_trial?.value || null,
|
||||
toCellValue: (i) => {
|
||||
if (studies[i].directions.length !== 1) {
|
||||
return "-" // Multi-objective study does not hold best_trial attribute.
|
||||
}
|
||||
return studies[i].best_trial?.values?.[0] || null
|
||||
},
|
||||
},
|
||||
{
|
||||
field: "study_name",
|
||||
|
||||
+3
-3
@@ -30,7 +30,7 @@ declare interface Trial {
|
||||
study_id: number
|
||||
number: number
|
||||
state: TrialState
|
||||
value?: number
|
||||
values?: number[]
|
||||
intermediate_values: TrialIntermediateValue[]
|
||||
datetime_start: Date
|
||||
datetime_complete?: Date
|
||||
@@ -42,7 +42,7 @@ declare interface Trial {
|
||||
declare interface StudySummary {
|
||||
study_id: number
|
||||
study_name: string
|
||||
direction: StudyDirection
|
||||
directions: StudyDirection[]
|
||||
best_trial?: Trial
|
||||
user_attrs: Attribute[]
|
||||
system_attrs: Attribute[]
|
||||
@@ -51,7 +51,7 @@ declare interface StudySummary {
|
||||
|
||||
declare interface StudyDetail {
|
||||
name: string
|
||||
direction: StudyDirection
|
||||
directions: StudyDirection[]
|
||||
datetime_start: Date
|
||||
best_trial?: Trial
|
||||
trials: Trial[]
|
||||
|
||||
Reference in New Issue
Block a user