Support Optuna v2.4.0

This commit is contained in:
c-bata
2021-01-12 19:25:23 +09:00
parent ff5fde29ff
commit a76e0e4f4a
8 changed files with 80 additions and 48 deletions
+4 -2
View File
@@ -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:
+4 -4
View File
@@ -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()
+8 -8
View File
@@ -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
View File
@@ -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[]