package water.api.schemas3;
import hex.Model;
import water.AutoBuffer;
import water.H2O;
import water.api.API;
import water.api.schemas3.KeyV3.ModelKeyV3;
import water.exceptions.H2OIllegalArgumentException;
import water.util.PojoUtils;
/**
* A Model schema contains all the pieces associated with a Model:
* <p>
* <ul>
* <li> an instance of a ModelParameters schema containing the build parameters</li>
* <li> an instance of a ModelResults schema containing the f00 b4r b4z</li>
* <li> an instance of a ModelMetrics schema</li>
* </ul>
*
*/
public class ModelSchemaV3<
M extends Model<M, P, O>,
S extends ModelSchemaV3<M, S, P, PS, O, OS>,
P extends Model.Parameters,
PS extends ModelParametersSchemaV3<P, PS>,
O extends Model.Output,
OS extends ModelOutputSchemaV3<O, OS>
> extends ModelSchemaBaseV3<M, S> {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAREFUL: This class has its own JSON serializer. If you add a field here you probably also want to add it to the serializer!
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Output fields
@API(help="The build parameters for the model (e.g. K for KMeans).", direction=API.Direction.OUTPUT)
public PS parameters;
@API(help="The build output for the model (e.g. the cluster centers for KMeans).", direction=API.Direction.OUTPUT)
public OS output;
@API(help="Compatible frames, if requested", direction=API.Direction.OUTPUT)
public String[] compatible_frames;
@API(help="Checksum for all the things that go into building the Model.", direction=API.Direction.OUTPUT)
protected long checksum;
public ModelSchemaV3() {}
public ModelSchemaV3(M m) {
super(m);
PojoUtils.copyProperties(this.parameters, m._parms, PojoUtils.FieldNaming.ORIGIN_HAS_UNDERSCORES);
PojoUtils.copyProperties(this.output, m._output, PojoUtils.FieldNaming.ORIGIN_HAS_UNDERSCORES);
}
//==========================
// Custom adapters go here
// TODO: I think we can implement the following two here, using reflection on the type parameters.
/** Factory method to create the model-specific parameters schema. */
public PS createParametersSchema() { throw H2O.fail("createParametersSchema() must be implemented in class: " + this.getClass()); }
/** Factory method to create the model-specific output schema. */
public OS createOutputSchema() { throw H2O.fail("createOutputSchema() must be implemented in class: " + this.getClass()); }
// Version&Schema-specific filling from the impl
@Override public S fillFromImpl(M m) {
this.data_frame = new KeyV3.FrameKeyV3(m._parms._train);
this.response_column_name = m._parms._response_column;
this.algo = m._parms.algoName().toLowerCase();
this.algo_full_name = m._parms.fullName();
// Key<? extends Model> k = m._key;
this.model_id = new ModelKeyV3<>(m._key);
this.checksum = m.checksum();
parameters = createParametersSchema();
parameters.fillFromImpl(m._parms);
parameters.model_id = model_id;
output = createOutputSchema();
output.fillFromImpl(m._output);
// noinspection unchecked
return (S)this; // have to cast because the definition of S doesn't include ModelSchemaV3
}
public final AutoBuffer writeJSON_impl( AutoBuffer ab ) {
ab.putJSONStr("algo", algo);
ab.put1(',');
ab.putJSONStr("algo_full_name", algo_full_name);
ab.put1(',');
ab.putJSON("model_id", model_id);
ab.put1(',');
// Builds ModelParameterSchemaV2 objects for each field, and then calls writeJSON on the array
try {
PS defaults = createParametersSchema().fillFromImpl(parameters.getImplClass().newInstance());
ModelParametersSchemaV3.writeParametersJSON(ab, parameters, defaults);
ab.put1(',');
}
catch (Exception e) {
String msg = "Error creating an instance of ModelParameters for algo: " + algo;
String dev_msg = "Error creating an instance of ModelParameters for algo: " + algo + ": " + this.getImplClass();
throw new H2OIllegalArgumentException(msg, dev_msg);
}
if (null == output) { // allow key-only output
output = createOutputSchema();
}
// Let output render itself:
ab.putJSON("output", output);
ab.put1(',');
ab.putJSONAStr("compatible_frames", compatible_frames);
return ab;
}
}