/*
* Project Name : Visual Python
* Description : GUI-based Python code generator
* File Name : Regression.js
* Author : Black Logic
* Note : Model selection and fitting
* License : GNU GPLv3 with Visual Python special exception
* Date : 2022. 02. 07
* Change Date :
*/
//============================================================================
// [CLASS] Regression
//============================================================================
define([
__VP_TEXT_LOADER__('vp_base/html/m_ml/model.html'), // INTEGRATION: unified version of text loader
'vp_base/js/com/com_util',
'vp_base/js/com/com_interface',
'vp_base/js/com/com_String',
'vp_base/js/com/com_generatorV2',
'vp_base/data/m_ml/mlLibrary',
'vp_base/js/com/component/PopupComponent',
'vp_base/js/com/component/VarSelector2',
'vp_base/js/com/component/ModelEditor'
], function(msHtml, com_util, com_interface, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, ModelEditor) {
/**
* Regression
*/
class Regression extends PopupComponent {
_init() {
super._init();
this.config.sizeLevel = 2;
this.config.dataview = false;
this.state = {
// model creation
modelControlType: 'creation',
modelType: 'ln-rgs',
userOption: '',
featureData: 'X_train',
targetData: 'y_train',
allocateToCreation: 'model',
// model selection
model: '',
method: '',
...this.state
}
this.modelConfig = ML_LIBRARIES;
this.modelTypeList = {
'Regression': ['ln-rgs', 'ridge', 'lasso', 'elasticnet', 'sv-rgs', 'dt-rgs', 'rf-rgs', 'gbm-rgs', 'xgb-rgs', 'lgbm-rgs', 'cb-rgs'],
}
}
_bindEvent() {
super._bindEvent();
/** Implement binding events */
var that = this;
// select model control type
$(this.wrapSelector('#modelControlType')).on('change', function() {
let modelControlType = $(this).val();
// show/hide model box
$(that.wrapSelector('.vp-model-box')).hide();
$(that.wrapSelector(`.vp-model-box[data-type="${modelControlType}"]`)).show();
});
// select model type
$(this.wrapSelector('#modelType')).on('change', function() {
let modelType = $(this).val();
that.state.modelType = modelType;
$(that.wrapSelector('.vp-model-option-box')).html(that.templateForOption(modelType));
that.viewOption();
// show install button
if (that.modelConfig[modelType].install != undefined) {
$(that.wrapSelector('#vp_installLibrary')).show();
} else {
$(that.wrapSelector('#vp_installLibrary')).hide();
}
});
// install library
$(this.wrapSelector('#vp_installLibrary')).on('click', function() {
let config = that.modelConfig[that.state.modelType];
if (config && config.install != undefined) {
// insert install code
let installCode = config.install;
if (vpConfig.extensionType === 'lite') {
installCode = installCode.replace('!', '%');
}
com_interface.insertCell('code', installCode, true, 'Machine Learning > Regression');
}
});
// change model
$(this.wrapSelector('#model')).on('change', function() {
that.modelEditor.reload();
})
}
templateForBody() {
let page = $(msHtml);
let that = this;
// model control type
$(page).find('.vp-model-box').hide();
$(page).find(`.vp-model-box[data-type="${this.state.modelControlType}"]`).show();
//================================================================
// Model creation
//================================================================
// model types
let modelTypeTag = new com_String();
Object.keys(this.modelTypeList).forEach(modelCategory => {
let modelOptionTag = new com_String();
that.modelTypeList[modelCategory].forEach(opt => {
let optConfig = that.modelConfig[opt];
let selectedFlag = '';
if (opt == that.state.modelType) {
selectedFlag = 'selected';
}
modelOptionTag.appendFormatLine('',
opt, selectedFlag, optConfig.name);
})
modelTypeTag.appendFormatLine('',
modelCategory, modelOptionTag.toString());
});
$(page).find('#modelType').html(modelTypeTag.toString());
// show install button
if (this.modelConfig[this.state.modelType].install != undefined) {
$(page).find('#vp_installLibrary').show();
} else {
$(page).find('#vp_installLibrary').hide();
}
// render option page
$(page).find('.vp-model-option-box').html(this.templateForOption(this.state.modelType));
let varSelector = new VarSelector2(this.wrapSelector());
varSelector.setComponentID('featureData');
varSelector.addClass('vp-state vp-input');
varSelector.setValue(this.state.featureData);
$(page).find('#featureData').replaceWith(varSelector.toTagString());
varSelector = new VarSelector2(this.wrapSelector());
varSelector.setComponentID('targetData');
varSelector.addClass('vp-state vp-input');
varSelector.setValue(this.state.targetData);
$(page).find('#targetData').replaceWith(varSelector.toTagString());
//================================================================
// Model selection
//================================================================
// set model list
let modelOptionTag = new com_String();
vpKernel.getModelList('Regression').then(function(resultObj) {
let { result } = resultObj;
var modelList = JSON.parse(result);
modelList && modelList.forEach(model => {
let selectFlag = '';
if (model.varName == that.state.model) {
selectFlag = 'selected';
}
modelOptionTag.appendFormatLine('',
model.varName, model.varType, selectFlag, model.varName, model.varType);
});
$(page).find('#model').html(modelOptionTag.toString());
$(that.wrapSelector('#model')).html(modelOptionTag.toString());
if (!that.state.model || that.state.model == '') {
that.state.model = $(that.wrapSelector('#model')).val();
}
that.modelEditor.reload();
});
//================================================================
// Load state
//================================================================
Object.keys(this.state).forEach(key => {
let tag = $(page).find('#' + key);
let tagName = $(tag).prop('tagName'); // returns with UpperCase
let value = that.state[key];
if (value == undefined) {
return;
}
switch(tagName) {
case 'INPUT':
let inputType = $(tag).prop('type');
if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') {
$(tag).val(value);
break;
}
if (inputType == 'checkbox') {
$(tag).prop('checked', value);
break;
}
break;
case 'TEXTAREA':
case 'SELECT':
default:
$(tag).val(value);
break;
}
});
return page;
}
templateForOption(modelType) {
let config = this.modelConfig[modelType];
let state = this.state;
let optBox = new com_String();
// render tag
config.options.forEach(opt => {
optBox.appendFormatLine(''
, opt.name, opt.name, com_util.optionToLabel(opt.name));
let content = com_generator.renderContent(this, opt.component[0], opt, state);
optBox.appendLine(content[0].outerHTML);
});
// render user option
optBox.appendFormatLine('', 'userOption', 'User option');
optBox.appendFormatLine('',
'userOption', 'key=value, ...', this.state.userOption);
return optBox.toString();
}
viewOption() {
// SVR - kernel selection
if (this.state.modelType == 'sv-rgs') {
let kernelType = this.state.kernel;
switch (kernelType) {
case undefined: // default = rbf
case '':
case 'rbf': // gamma
$(this.wrapSelector('label[for="gamma"]')).show();
$(this.wrapSelector('#gamma')).show();
// hide others
$(this.wrapSelector('label[for="degree"]')).hide();
$(this.wrapSelector('#degree')).hide();
$(this.wrapSelector('label[for="coef0"]')).hide();
$(this.wrapSelector('#coef0')).hide();
break;
case 'poly': // gamma / degree / coef0
$(this.wrapSelector('label[for="gamma"]')).show();
$(this.wrapSelector('#gamma')).show();
$(this.wrapSelector('label[for="degree"]')).show();
$(this.wrapSelector('#degree')).show();
$(this.wrapSelector('label[for="coef0"]')).show();
$(this.wrapSelector('#coef0')).show();
break;
case 'sigmoid': // gamma / coef0
$(this.wrapSelector('label[for="gamma"]')).show();
$(this.wrapSelector('#gamma')).show();
$(this.wrapSelector('label[for="coef0"]')).show();
$(this.wrapSelector('#coef0')).show();
// hide others
$(this.wrapSelector('label[for="degree"]')).hide();
$(this.wrapSelector('#degree')).hide();
break;
default:
// hide others
$(this.wrapSelector('label[for="gamma"]')).hide();
$(this.wrapSelector('#gamma')).hide();
$(this.wrapSelector('label[for="degree"]')).hide();
$(this.wrapSelector('#degree')).hide();
$(this.wrapSelector('label[for="coef0"]')).hide();
$(this.wrapSelector('#coef0')).hide();
break;
}
// Model Creation - SVC kernel selection
let that = this;
$(this.wrapSelector('#kernel')).off('change');
$(this.wrapSelector('#kernel')).change(function() {
that.state.kernel = $(this).val();
that.viewOption();
});
}
}
render() {
super.render();
// Model Creation - dynamically view options
this.viewOption();
// Model Editor
this.modelEditor = new ModelEditor(this, "model", "instanceEditor");
}
generateCode() {
let { modelControlType, modelType, userOption, allocateToCreation, model } = this.state;
let code = new com_String();
if (modelControlType == 'creation') {
/**
* Model Creation
* ---
* from module import model_function
* model = Model(key=value, ...)
*/
let config = this.modelConfig[modelType];
code.appendLine(config.import);
code.appendLine();
// model code
let modelCode = config.code;
modelCode = com_generator.vp_codeGenerator(this, config, this.state, (userOption != ''? ', ' + userOption : ''));
code.appendFormat('{0} = {1}', allocateToCreation, modelCode);
} else {
/**
* Model Selection
* ---
* ...
*/
code.append(this.modelEditor.getCode({'${model}': model}));
}
return code.toString();
}
}
return Regression;
});