diff --git a/css/boardFrame.css b/css/boardFrame.css index 57bf5ab6..1614a371 100644 --- a/css/boardFrame.css +++ b/css/boardFrame.css @@ -238,11 +238,11 @@ background-color: rgb(253, 177, 133); } .vp-block.machine_learning .vp-block-header { - background-color: rgb(249, 227, 214); + background-color: #E8ECD0; } .vp-block.machine_learning.vp-focus .vp-block-header, .vp-block.machine_learning.vp-focus-child .vp-block-header { - background-color: rgb(253, 177, 133); + background-color: #C6CE94; } .vp-block.logic-define .vp-block-header { background-color: rgb(213, 231, 222); diff --git a/css/component/instanceEditor.css b/css/component/instanceEditor.css index 922872b3..4f321f65 100644 --- a/css/component/instanceEditor.css +++ b/css/component/instanceEditor.css @@ -17,8 +17,8 @@ .vp-ins-select-container .vp-ins-search-icon { position: absolute; color: #C4C4C4; - right: 5px; - top: 5px; + right: 7px; + top: 7px; } .vp-ins-select-box { margin-top: 5px; @@ -74,6 +74,10 @@ .vp-ins-parameter-box { grid-column: 1/3; } +.vp-ins-parameter-box:empty::after { + content: '(Empty)'; + color: var(--gray-color); +} .vp-ins-parameter { width: 100% !important; } diff --git a/css/menuFrame.css b/css/menuFrame.css index 68303d1e..2e3bec6f 100644 --- a/css/menuFrame.css +++ b/css/menuFrame.css @@ -229,6 +229,15 @@ .vp-menuitem.apps.vp-color-apps4 { background: #E56139; } +.vp-menuitem.apps.vp-color-apps5 { + background: #BEB727; +} +.vp-menuitem.apps.vp-color-apps6 { + background: #91A541; +} +.vp-menuitem.apps.vp-color-apps7 { + background: #718E41; +} .vp-menuitem.apps.vp-color-preparing { background: var(--gray-color); } diff --git a/data/libraries.json b/data/libraries.json index d2e0cad9..c04ad2a8 100644 --- a/data/libraries.json +++ b/data/libraries.json @@ -3111,8 +3111,8 @@ "desc" : "Data sets for machine learning", "file" : "m_ml/DataSets", "apps" : { - "color": 1, - "icon": "apps/apps_white.svg" + "color": 5, + "icon": "apps/apps_dataset.svg" } }, { @@ -3125,8 +3125,8 @@ "desc" : "Data preparation for machine learning", "file" : "m_ml/DataPrep", "apps" : { - "color": 1, - "icon": "apps/apps_white.svg" + "color": 5, + "icon": "apps/apps_dataprep.svg" } }, { @@ -3139,7 +3139,7 @@ "desc" : "Data split for machine learning", "file" : "m_ml/dataSplit", "apps" : { - "color": 1, + "color": 5, "icon": "apps/apps_datasplit.svg" } }, @@ -3147,28 +3147,28 @@ "id" : "ml_regression", "type" : "function", "level": 1, - "name" : "Regression", + "name" : "Regressor", "tag" : "REGRESSION,MODEL,MACHINE LEARNING,ML", "path" : "visualpython - machine_learning - regression", "desc" : "Regression model for machine learning", "file" : "m_ml/Regression", "apps" : { - "color": 1, - "icon": "apps/apps_model.svg" + "color": 5, + "icon": "apps/apps_regression.svg" } }, { "id" : "ml_classification", "type" : "function", "level": 1, - "name" : "Classification", + "name" : "Classifier", "tag" : "CLASSIFICATION,MODEL,MACHINE LEARNING,ML", "path" : "visualpython - machine_learning - classification", "desc" : "Classification model for machine learning", "file" : "m_ml/Classification", "apps" : { - "color": 1, - "icon": "apps/apps_model.svg" + "color": 6, + "icon": "apps/apps_classification.svg" } }, { @@ -3181,22 +3181,22 @@ "desc" : "Clustering model for machine learning", "file" : "m_ml/Clustering", "apps" : { - "color": 1, - "icon": "apps/apps_model.svg" + "color": 6, + "icon": "apps/apps_clustering.svg" } }, { "id" : "ml_dimensionReduction", "type" : "function", "level": 1, - "name" : "Dimension Reduction", + "name" : "Dimension", "tag" : "DIMENSION REDUCTION,MODEL,MACHINE LEARNING,ML", "path" : "visualpython - machine_learning - dimension_reduction", "desc" : "Dimension reduction model for machine learning", "file" : "m_ml/DimensionReduction", "apps" : { - "color": 1, - "icon": "apps/apps_model.svg" + "color": 6, + "icon": "apps/apps_dimension.svg" } }, { @@ -3209,8 +3209,8 @@ "desc" : "AutoML model for machine learning", "file" : "m_ml/AutoML", "apps" : { - "color": 1, - "icon": "apps/apps_model.svg" + "color": 6, + "icon": "apps/apps_automl.svg" } }, { @@ -3223,7 +3223,7 @@ "desc" : "Performance evaluation for machine learning", "file" : "m_ml/evaluation", "apps" : { - "color": 1, + "color": 7, "icon": "apps/apps_evaluate.svg" } } diff --git a/data/m_ml/mlLibrary.js b/data/m_ml/mlLibrary.js index 6119e80a..df44f019 100644 --- a/data/m_ml/mlLibrary.js +++ b/data/m_ml/mlLibrary.js @@ -20,13 +20,118 @@ define([ * ] */ var ML_LIBRARIES = { + /** Data Sets */ + 'load_boston': { + name: 'load_boston', + import: 'from sklearn.datasets import load_boston', + code: 'load_boston()', + options: [ + + ] + }, + 'load_iris': { + name: 'load_iris', + import: 'from sklearn.datasets import load_iris', + code: 'load_iris()', + options: [ + + ] + }, + 'load_diabetes': { + name: 'load_diabetes', + import: 'from sklearn.datasets import load_diabetes', + code: 'load_diabetes()', + options: [ + + ] + }, + 'load_digits': { + name: 'load_digits', + import: 'from sklearn.datasets import load_digits', + code: 'load_digits(${n_class})', + options: [ + { name: 'n_class', component: ['input_number'], default: 10, usePair: true }, + ] + }, + 'load_linnerud': { + name: 'load_linnerud', + import: 'from sklearn.datasets import load_linnerud', + code: 'load_linnerud()', + options: [ + + ] + }, + 'load_wine': { + name: 'load_wine', + import: 'from sklearn.datasets import load_wine', + code: 'load_wine()', + options: [ + + ] + }, + 'load_breast_cancer': { + name: 'load_breast_cancer', + import: 'from sklearn.datasets import load_breast_cancer', + code: 'load_breast_cancer()', + options: [ + + ] + }, + 'make_classification': { + name: 'make_classification', + import: 'from sklearn.datasets import make_classification', + code: 'make_classification(${n_samples}${n_features}${n_repeated}${n_classes}${shuffle}${random_state}${etc})', + options: [ + { name: 'n_samples', component: ['input_number'], default: 100, usePair: true }, + { name: 'n_features', component: ['input_number'], default: 20, usePair: true }, + { name: 'n_repeated', component: ['input_number'], default: 0, usePair: true }, + { name: 'n_classes', component: ['input_number'], default: 2, usePair: true }, + { name: 'shuffle', component: ['bool_select'], default: 'True', usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + 'make_blobs': { + name: 'make_blobs', + import: 'from sklearn.datasets import make_blobs', + code: 'make_blobs(${n_samples}${n_features}${shuffle}${random_state}${etc})', + options: [ + { name: 'n_samples', component: ['input_number'], default: 100, usePair: true }, + { name: 'n_features', component: ['input_number'], default: 20, usePair: true }, + { name: 'shuffle', component: ['bool_select'], default: 'True', usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + 'make_circles': { + name: 'make_circles', + import: 'from sklearn.datasets import make_circles', + code: 'make_circles(${n_samples}${shuffle}${noise}${random_state}${factor}${etc})', + options: [ + { name: 'n_samples', component: ['input_number'], default: 100, usePair: true }, + { name: 'shuffle', component: ['bool_select'], default: 'True', usePair: true }, + { name: 'noise', component: ['input_number'], usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true }, + { name: 'factor', component: ['input_number'], default: 0.8, usePair: true } + ] + }, + 'make_moons': { + name: 'make_moons', + import: 'from sklearn.datasets import make_moons', + code: 'make_moons(${n_samples}${shuffle}${noise}${random_state}${etc})', + options: [ + { name: 'n_samples', component: ['input_number'], default: 100, usePair: true }, + { name: 'shuffle', component: ['bool_select'], default: 'True', usePair: true }, + { name: 'noise', component: ['input_number'], usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, /** Data Preparation - Encoding */ 'prep-onehot': { name: 'OneHotEncoder', import: 'from sklearn.preprocessing import OneHotEncoder', - code: 'OneHotEncoder()', + code: 'OneHotEncoder(${handle_unknown}${etc})', options: [ - + { name: 'handle_unknown', component: ['option_suggest'], usePair: true, + options: ['error', 'ignore'], default: 'error' }, ] }, 'prep-label': { @@ -40,66 +145,77 @@ define([ 'prep-ordinal': { name: 'OrdinalEncoder', import: 'from sklearn.preprocessing import OrdinalEncoder', - code: 'OrdinalEncoder()', + code: 'OrdinalEncoder(${handle_unknown}${unknown_values}${etc})', options: [ - + { name: 'handle_unknown', component: ['option_suggest'], usePair: true, + options: ['error', 'use_encoded_value'], default: 'error' }, + { name: 'unknown_values', component: ['input'], usePair: true } ] }, 'prep-target': { name: 'TargetEncoder', install: '!pip install category_encoders', import: 'from category_encoders.target_encoder import TargetEncoder', - code: 'TargetEncoder()', + code: 'TargetEncoder(${cols}${handle_missing}${handle_unknown}${smoothing}${etc})', options: [ - + { name: 'cols', component: ['var_suggest', '1darr'], usePair: true }, + { name: 'handle_missing', component: ['option_suggest'], usePair: true, + options: ['error', 'return_nan', 'value'], default: 'value' }, + { name: 'handle_unknown', component: ['option_suggest'], usePair: true, + options: ['error', 'return_nan', 'value'], default: 'value' }, + { name: 'smoothing', component: ['input_number'], default: 1.0, usePair: true } ] }, 'prep-smote': { name: 'SMOTE', install: '!pip install imblearn', - import: 'from imlearn.over_sampling import SMOTE', - code: 'SMOTE()', + import: 'from imblearn.over_sampling import SMOTE', + code: 'SMOTE(${random_state}${k_neighbors}${etc})', options: [ - + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true }, + { name: 'k_neighbors', component: ['input_number'], default: 5, usePair: true } ] }, /** Data Preparation - Scaling */ 'prep-standard': { name: 'StandardScaler', import: 'from sklearn.preprocessing import StandardScaler', - code: 'StandardScaler()', + code: 'StandardScaler(${with_mean}${with_std}${etc})', options: [ - + { name: 'with_mean', component: ['bool_select'], default: 'True', usePair: true }, + { name: 'with_std', component: ['bool_select'], default: 'True', usePair: true } ] }, 'prep-robust': { name: 'RobustScaler', import: 'from sklearn.preprocessing import RobustScaler', - code: 'RobustScaler()', + code: 'RobustScaler(${with_centering}${with_scaling}${etc})', options: [ - + { name: 'with_centering', component: ['bool_select'], default: 'True', usePair: true }, + { name: 'with_scaling', component: ['bool_select'], default: 'True', usePair: true } ] }, 'prep-minmax': { name: 'MinMaxScaler', import: 'from sklearn.preprocessing import MinMaxScaler', - code: 'MinMaxScaler()', + code: 'MinMaxScaler(${feature_range}${etc})', options: [ - + { name: 'feature_range', component: ['input'], placeholder: '(min, max)', default: '(0, 1)', usePair: true } ] }, 'prep-normalizer': { name: 'Normalizer', import: 'from sklearn.preprocessing import Normalizer', - code: 'Normalizer()', + code: 'Normalizer(${norm}${etc})', options: [ - + { name: 'norm', component: ['option_suggest'], usePair: true, + options: ['l1', 'l2', 'max'], default: 'l2' }, ] }, 'prep-func-trsfrm-log': { name: 'Log Scaling', import: 'from sklearn.preprocessing import FunctionTransformer', - code: 'FunctionTransformer(np.log1p)', + code: 'FunctionTransformer(np.log1p${etc})', options: [ ] @@ -107,7 +223,15 @@ define([ 'prep-func-trsfrm-exp': { name: 'Exponential Scaling', import: 'from sklearn.preprocessing import FunctionTransformer', - code: 'FunctionTransformer(np.expm1)', + code: 'FunctionTransformer(np.expm1${etc})', + options: [ + + ] + }, + 'prep-poly-feat': { + name: 'Polynomial Features', + import: 'from sklearn.preprocessing import PolynomialFeatures', + code: 'PolynomialFeatures(${etc})', options: [ ] @@ -116,18 +240,42 @@ define([ 'ln-rgs': { name: 'LinearRegression', import: 'from sklearn.linear_model import LinearRegression', - code: 'LinearRegression(${fit_intercept})', + code: 'LinearRegression(${fit_intercept}${etc})', options: [ { name: 'fit_intercept', component: ['bool_select'], default: 'True', usePair: true } ] }, + 'ridge': { + name: 'Ridge', + import: 'from sklearn.linear_model import Ridge', + code: 'Ridge(${etc})', + options: [ + //TODO: + ] + }, + 'lasso': { + name: 'Lasso', + import: 'from sklearn.linear_model import Lasso', + code: 'Lasso(${etc})', + options: [ + //TODO: + ] + }, + 'elasticnet': { + name: 'ElasticNet', + import: 'from sklearn.linear_model import ElasticNet', + code: 'ElasticNet(${etc})', + options: [ + //TODO: + ] + }, 'sv-rgs': { name: 'SVR', import: 'from sklearn.svm import SVR', code: 'SVR(${C}${kernel}${gamma}${random_state}${etc})', options: [ { name: 'C', component: ['input_number'], placeholder: '1.0', usePair: true }, - { name: 'kernel', component: ['option_select'], default: 'rbf', type:'text', usePair: true, + { name: 'kernel', component: ['option_select'], type: 'text', default: 'rbf', type:'text', usePair: true, options: ['linear', 'poly', 'rbf', 'sigmoid', 'precomputed'] }, { name: 'gamma', component: ['option_suggest'], default: 'scale', type:'text', usePair: true, options: ['scale', 'auto'] }, @@ -139,7 +287,7 @@ define([ import: 'from sklearn.tree import DecisionTreeRegressor', code: 'DecisionTreeRegressor(${criterion}${max_depth}${min_samples_split}${random_state}${etc})', options: [ - { name: 'criterion', component: ['option_select'], default: 'squared_error', type:'text', + { name: 'criterion', component: ['option_select'], type: 'text', default: 'squared_error', type:'text', options: ['squared_error', 'friedman_mse', 'absolute_error', 'poisson'] }, { name: 'max_depth', component: ['input_number'], placeholder: 'None', usePair: true }, { name: 'min_samples_split', component: ['input_number'], default: 2, usePair: true }, @@ -152,7 +300,7 @@ define([ code: 'RandomForestRegressor(${n_estimators}${criterion}${max_depth}${min_samples_split}${n_jobs}${random_state}${etc})', options: [ { name: 'n_estimators', component: ['input_number'], default: 100, usePair: true }, - { name: 'criterion', component: ['option_select'], default: 'squared_error', type:'text', usePair: true, + { name: 'criterion', component: ['option_select'], type: 'text', default: 'squared_error', type:'text', usePair: true, options: ['squared_error', 'absolute_error', 'poisson'] }, { name: 'max_depth', component: ['input_number'], placeholder: 'None', usePair: true }, { name: 'min_samples_split', component: ['input_number'], default: 2, usePair: true }, @@ -165,11 +313,11 @@ define([ import: 'from sklearn.ensemble import GradientBoostingRegressor', code: 'GradientBoostingRegressor(${loss}${learning_rate}${n_estimators}${criterion}${random_state}${etc})', options: [ - { name: 'loss', component: ['option_select'], default: 'squared_error', type:'text', usePair: true, + { name: 'loss', component: ['option_select'], type: 'text', default: 'squared_error', type:'text', usePair: true, options: ['squared_error', 'absolute_error', 'huber', 'quantile'] }, { name: 'learning_rate', component: ['input_number'], default: 0.1, usePair: true }, { name: 'n_estimators', component: ['input_number'], default: 100, usePair: true }, - { name: 'criterion', component: ['option_select'], default: 'friedman_mse', type:'text', usePair: true, + { name: 'criterion', component: ['option_select'], type: 'text', default: 'friedman_mse', type:'text', usePair: true, options: ['friedman_mse', 'squared_error', 'mse', 'mae'] }, { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } ] @@ -193,7 +341,7 @@ define([ import: 'from lightgbm import LGBMRegressor', code: 'LGBMRegressor(${boosting_type}${max_depth}${learning_rate}${n_estimators}${random_state}${etc})', options: [ - { name: 'boosting_type', component: ['option_select'], default: 'gbdt', type: 'text', usePair: true, + { name: 'boosting_type', component: ['option_select'], type: 'text', default: 'gbdt', type: 'text', usePair: true, options: ['gbdt', 'dart', 'goss', 'rf']}, { name: 'max_depth', component: ['input_number'], placeholder: '-1', usePair: true }, { name: 'learning_rate', component: ['input_number'], default: 0.1, usePair: true }, @@ -208,9 +356,9 @@ define([ code: 'CatBoostRegressor(${learning_rate}${loss_function}${task_type}${max_depth}${n_estimators}${random_state}${etc})', options: [ { name: 'learning_rate', component: ['input_number'], placeholder: 'None', usePair: true }, - { name: 'loss_function', component: ['option_select'], default: 'RMSE', type:'text', usePair: true, + { name: 'loss_function', component: ['option_select'], type: 'text', default: 'RMSE', type:'text', usePair: true, options: ['RMSE', 'absolute_error', 'huber', 'quantile'] }, - { name: 'task_type', component: ['option_select'], default: 'CPU', usePair: true, + { name: 'task_type', component: ['option_select'], type: 'text', default: 'CPU', usePair: true, options: ['CPU', 'GPU'] }, { name: 'max_depth', component: ['input_number'], placeholder: 'None', usePair: true }, { name: 'n_estimators', component: ['input_number'], placeholder: 'None', usePair: true }, @@ -223,18 +371,42 @@ define([ import: 'from sklearn.linear_model import LogisticRegression', code: 'LogisticRegression(${penalty}${C}${random_state}${etc})', options: [ - { name: 'penalty', component: ['option_select'], default: 'l2', usePair: true, options: ['l1', 'l2', 'elasticnet', 'none']}, + { name: 'penalty', component: ['option_select'], type: 'text', default: 'l2', usePair: true, options: ['l1', 'l2', 'elasticnet', 'none']}, { name: 'C', component: ['input_number'], placeholder: '1.0', usePair: true }, { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } ] }, + 'bern-nb': { + name: 'BernoulliNB', + import: 'from sklearn.naive_bayes import BernoulliNB', + code: 'BernoulliNB(${etc})', + options: [ + //TODO: + ] + }, + 'mulnom-nb': { + name: 'MultinomialNB', + import: 'from sklearn.naive_bayes import MultinomialNB', + code: 'MultinomialNB(${etc})', + options: [ + //TODO: + ] + }, + 'gaus-nb': { + name: 'GaussianNB', + import: 'from sklearn.naive_bayes import GaussianNB', + code: 'GaussianNB(${etc})', + options: [ + //TODO: + ] + }, 'sv-clf': { name: 'SupportVectorClassifier', import: 'from sklearn.svm import SVC', code: 'SVC(${C}${kernel}${gamma}${random_state}${etc})', options: [ { name: 'C', component: ['input_number'], placeholder: '1.0', usePair: true }, - { name: 'kernel', component: ['option_select'], usePair: true, + { name: 'kernel', component: ['option_select'], type: 'text', usePair: true, options: ['linear', 'poly', 'rbf', 'sigmoid', 'precomputed'], default: 'rbf' }, { name: 'gamma', component: ['option_suggest'], usePair: true, options: ['scale', 'auto'], default: 'scale' }, @@ -246,7 +418,7 @@ define([ import: 'from sklearn.tree import DecisionTreeClassifier', code: 'DecisionTreeClassifier(${criterion}${max_depth}${min_samples_split}${random_state}${etc})', options: [ - { name: 'criterion', component: ['option_select'], default: 'squared_error', type:'text', + { name: 'criterion', component: ['option_select'], type: 'text', default: 'squared_error', type:'text', options: ['squared_error', 'friedman_mse', 'absolute_error', 'poisson'], usePair: true }, { name: 'max_depth', component: ['input_number'], placeholder: 'None', usePair: true }, { name: 'min_samples_split', component: ['input_number'], default: 2, usePair: true }, @@ -259,7 +431,7 @@ define([ code: 'RandomForestClassifier(${n_estimators}${criterion}${max_depth}${min_samples_split}${n_jobs}${random_state}${etc})', options: [ { name: 'n_estimators', component: ['input_number'], default: 100, usePair: true }, - { name: 'criterion', component: ['option_select'], default: 'gini', type:'text', usePair: true, + { name: 'criterion', component: ['option_select'], type: 'text', default: 'gini', type:'text', usePair: true, options: ['gini', 'entropy'] }, { name: 'max_depth', component: ['input_number'], placeholder: 'None', usePair: true }, { name: 'min_samples_split', component: ['input_number'], default: 2, usePair: true }, @@ -272,11 +444,11 @@ define([ import: 'from sklearn.ensemble import GradientBoostingClassifier', code: 'GradientBoostingClassifier(${loss}${learning_rate}${n_estimators}${criterion}${random_state}${etc})', options: [ - { name: 'loss', component: ['option_select'], default: 'deviance', type: 'text', usePair: true, + { name: 'loss', component: ['option_select'], type: 'text', default: 'deviance', type: 'text', usePair: true, options: ['deviance', 'exponential'] }, { name: 'learning_rate', component: ['input_number'], default: 0.1, usePair: true }, { name: 'n_estimators', component: ['input_number'], default: 100, usePair: true }, - { name: 'criterion', component: ['option_select'], default: 'friedman_mse', type:'text', usePair: true, + { name: 'criterion', component: ['option_select'], type: 'text', default: 'friedman_mse', type:'text', usePair: true, options: ['friedman_mse', 'squared_error', 'mse', 'mae'] }, { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } ] @@ -300,7 +472,7 @@ define([ import: 'from lightgbm import LGBMClassifier', code: 'LGBMClassifier(${boosting_type}${max_depth}${learning_rate}${n_estimators}${random_state}${etc})', options: [ - { name: 'boosting_type', component: ['option_select'], default: 'gbdt', type: 'text', usePair: true, + { name: 'boosting_type', component: ['option_select'], type: 'text', default: 'gbdt', type: 'text', usePair: true, options: ['gbdt', 'dart', 'goss', 'rf']}, { name: 'max_depth', component: ['input_number'], placeholder: '-1', usePair: true }, { name: 'learning_rate', component: ['input_number'], default: 0.1, usePair: true }, @@ -315,9 +487,9 @@ define([ code: 'CatBoostClassifier(${learning_rate}${loss_function}${task_type}${max_depth}${n_estimators}${random_state}${etc})', options: [ { name: 'learning_rate', component: ['input_number'], placeholder: 'None', usePair: true }, - { name: 'loss_function', component: ['option_select'], default: 'RMSE', type:'text', usePair: true, + { name: 'loss_function', component: ['option_select'], type: 'text', default: 'RMSE', type:'text', usePair: true, options: ['RMSE', 'absolute_error', 'huber', 'quantile'] }, - { name: 'task_type', component: ['option_select'], default: 'CPU', usePair: true, + { name: 'task_type', component: ['option_select'], type: 'text', default: 'CPU', usePair: true, options: ['CPU', 'GPU'] }, { name: 'max_depth', component: ['input_number'], placeholder: 'None', usePair: true }, { name: 'n_estimators', component: ['input_number'], placeholder: 'None', usePair: true }, @@ -325,8 +497,19 @@ define([ ] }, /** Auto ML */ + 'auto-sklearn-rgs': { + name: 'AutoSklearnRegressor (Linux only)', + install: '!pip install auto-sklearn', + import: 'from autosklearn.regression import AutoSklearnRegressor', + link: 'https://automl.github.io/auto-sklearn/master/api.html#regression', + code: 'AutoSklearnRegressor(${etc})', + options: [ + + ] + }, 'tpot-rgs': { name: 'TPOTRegressor', + install: '!pip install tpot', import: 'from tpot import TPOTRegressor', code: 'TPOTRegressor(${generation}${population_size}${cv}${random_state}${etc})', options: [ @@ -336,8 +519,19 @@ define([ { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } ] }, + 'auto-sklearn-clf': { + name: 'AutoSklearnClassifier (Linux only)', + install: '!pip install auto-sklearn', + import: 'from autosklearn.classification import AutoSklearnClassifier', + link: 'https://automl.github.io/auto-sklearn/master/api.html#classification', + code: 'AutoSklearnClassifier(${etc})', + options: [ + + ] + }, 'tpot-clf': { name: 'TPOTClassifier', + install: '!pip install tpot', import: 'from tpot import TPOTClassifier', code: 'TPOTClassifier(${generation}${population_size}${cv}${random_state}${etc})', options: [ @@ -386,7 +580,7 @@ define([ }, /** Dimension Reduction */ 'pca': { - name: 'Principal Component Analysis', + name: 'PCA(Principal Component Analysis)', import: 'from sklearn.decomposition import PCA', code: 'PCA(${n_components}${random_state}${etc})', options: [ @@ -395,7 +589,7 @@ define([ ] }, 'lda': { - name: 'Linear Discriminant Analysis', + name: 'LDA(Linear Discriminant Analysis)', import: 'from sklearn.discriminant_analysis import LinearDiscriminantAnalysis', code: 'LinearDiscriminantAnalysis(${n_components}${etc})', options: [ @@ -412,13 +606,23 @@ define([ ] }, 'nmf': { - name: 'Non-Negative Matrix Factorization', + name: 'NMF(Non-Negative Matrix Factorization)', import: 'from sklearn.decomposition import NMF', code: 'NMF(${n_components}${random_state}${etc})', options: [ { name: 'n_components', component: ['input_number'], placeholder: 'None', usePair: true }, { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } ] + }, + 'tsne': { + name: 'TSNE(T-distributed Stochastic Neighbor Embedding)', + import: 'from sklearn.manifold import TSNE', + code: 'TSNE(${n_components}${learning_rate}${random_state}${etc})', + options: [ + { name: 'n_components', component: ['input_number'], placeholder: 'None', usePair: true }, + { name: 'learning_rate', component: ['input_number'], default: 200.0, usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] } } diff --git a/html/m_ml/dataSets.html b/html/m_ml/dataSets.html new file mode 100644 index 00000000..5af731b8 --- /dev/null +++ b/html/m_ml/dataSets.html @@ -0,0 +1,19 @@ + +
+
+
+ + +
+
+ +
+
+
+ + +
+
+ \ No newline at end of file diff --git a/html/m_ml/evaluation.html b/html/m_ml/evaluation.html index b263afc7..2c23bf1c 100644 --- a/html/m_ml/evaluation.html +++ b/html/m_ml/evaluation.html @@ -7,11 +7,9 @@
@@ -20,6 +18,15 @@
+
+ + + + + + + +
@@ -28,19 +35,14 @@ -
-
- - - - - - - + +
- + + +
diff --git a/html/m_ml/model.html b/html/m_ml/model.html index 630ed259..4c26c1c4 100644 --- a/html/m_ml/model.html +++ b/html/m_ml/model.html @@ -20,20 +20,14 @@
- - - - -
-
- - + +
-
@@ -42,6 +36,15 @@
+
+ +
+ \ No newline at end of file diff --git a/html/menuFrame.html b/html/menuFrame.html index 084cba6e..37919802 100644 --- a/html/menuFrame.html +++ b/html/menuFrame.html @@ -51,7 +51,7 @@
-
+
diff --git a/img/apps/apps_automl.svg b/img/apps/apps_automl.svg new file mode 100644 index 00000000..06a0ff7f --- /dev/null +++ b/img/apps/apps_automl.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/img/apps/apps_classification.svg b/img/apps/apps_classification.svg new file mode 100644 index 00000000..5e6d91ea --- /dev/null +++ b/img/apps/apps_classification.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/img/apps/apps_clustering.svg b/img/apps/apps_clustering.svg new file mode 100644 index 00000000..ae50c87c --- /dev/null +++ b/img/apps/apps_clustering.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/img/apps/apps_dataprep.svg b/img/apps/apps_dataprep.svg new file mode 100644 index 00000000..7219b79b --- /dev/null +++ b/img/apps/apps_dataprep.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/img/apps/apps_dataset.svg b/img/apps/apps_dataset.svg new file mode 100644 index 00000000..37028753 --- /dev/null +++ b/img/apps/apps_dataset.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/img/apps/apps_dimension.svg b/img/apps/apps_dimension.svg new file mode 100644 index 00000000..264f3902 --- /dev/null +++ b/img/apps/apps_dimension.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/img/apps/apps_regression.svg b/img/apps/apps_regression.svg new file mode 100644 index 00000000..cb67005f --- /dev/null +++ b/img/apps/apps_regression.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/js/board/BoardFrame.js b/js/board/BoardFrame.js index 0a764153..caf61fb6 100644 --- a/js/board/BoardFrame.js +++ b/js/board/BoardFrame.js @@ -90,7 +90,7 @@ define([ let menu = $(this).data('menu'); switch (menu) { case 'new': - that.createNewNote(); + that.createNewNoteWithChecking(); break; case 'open': that.openNote(); @@ -111,7 +111,7 @@ define([ that.exportCode(); break; case 'clear': - that.clearBoard(); + that.clearBoardWithChecking(); break; } }); @@ -429,9 +429,51 @@ define([ //======================================================================== // Note control //======================================================================== - createNewNote() { - // TODO: alert before closing + /** + * Check if note has changes to save + */ + checkNote() { + if (this.blockList.length > 0) { + return true; + } + return false; + } + createNewNoteWithChecking() { + // alert before closing + let that = this; + if (this.checkNote()) { + // render update modal + com_util.renderModal({ + title: 'Save changes', + message: 'Do you want to save changes?', + buttons: ['Cancel', "No", 'Save'], + defaultButtonIdx: 0, + buttonClass: ['cancel', '', 'activated'], + finish: function(clickedBtnIdx) { + switch (clickedBtnIdx) { + case 0: + // cancel - do nothing + return; + case 1: + // don't save + that.createNewNote(); + break; + case 2: + // save + that.saveAsNote(function() { + that.createNewNote(); + }); + break; + } + } + }); + + return; + } + this.createNewNote(); + } + createNewNote() { // clear board before create new note this.clearBoard(); @@ -502,7 +544,7 @@ define([ this.saveAsNote(); } - saveAsNote() { + saveAsNote(callback) { let that = this; // save file navigation let fileNavi = new FileNavigation({ @@ -525,6 +567,8 @@ define([ that.tmpState.boardTitle = boardTitle; that.tmpState.boardPath = boardPath; $('#vp_boardTitle').val(boardTitle); + + callback(); } }); fileNavi.open(); @@ -542,9 +586,22 @@ define([ let prevNewLine = idx > 0?'\n':''; let indent = ' '.repeat((groupBlock.depth - rootBlockDepth) * indentCount); let thisBlockCode = groupBlock.popup.generateCode(); - // set indent to every line of thisblockcode - thisBlockCode = thisBlockCode.replaceAll('\n', '\n' + indent); - code.appendFormat('{0}{1}{2}', prevNewLine, indent, thisBlockCode); + if (Array.isArray(thisBlockCode)) { + for (let i = 0; i < thisBlockCode.length; i++) { + thisBlockCode[i] = thisBlockCode[i].replaceAll('\n', '\n' + indent); + } + if (addcell) { + // insert single cell using prev code + com_interface.insertCell('code', code.toString(), execute, block.blockNumber); + code = new com_String(); + // insert cells using this block code list + com_interface.insertCells('code', thisBlockCode, execute, block.blockNumber); + } + } else { + // set indent to every line of thisblockcode + thisBlockCode = thisBlockCode.replaceAll('\n', '\n' + indent); + code.appendFormat('{0}{1}{2}', prevNewLine, indent, thisBlockCode); + } }); if (addcell) { com_interface.insertCell('code', code.toString(), execute, block.blockNumber); @@ -625,6 +682,41 @@ define([ // // reloadBlockList // this.reloadBlockList(); // } + clearBoardWithChecking() { + // alert before closing + let that = this; + if (this.checkNote()) { + // render update modal + com_util.renderModal({ + title: 'Save changes', + message: 'Do you want to save changes?', + buttons: ['Cancel', "No", 'Save'], + defaultButtonIdx: 0, + buttonClass: ['cancel', '', 'activated'], + finish: function(clickedBtnIdx) { + switch (clickedBtnIdx) { + case 0: + // cancel - do nothing + return; + case 1: + // don't save + that.clearBoard(); + break; + case 2: + // save + that.saveAsNote(function() { + that.clearBoard(); + }); + break; + } + } + }); + + return; + } + + this.clearBoard(); + } clearBoard() { // TODO: alert before clearing let that = this; diff --git a/js/com/com_Config.js b/js/com/com_Config.js index 74987dba..ada98e73 100644 --- a/js/com/com_Config.js +++ b/js/com/com_Config.js @@ -483,25 +483,25 @@ define([ */ Config.ML_DATA_DICT = { 'Regression': [ - 'LinearRegression', 'SVR', 'DecisionTreeRegressor', 'RandomForestRegression', 'GradientBoostingRegressor', 'XGBRegressor', 'LGBMRegressor', 'CatBoostRegressor', + 'LinearRegression', 'Ridge', 'Lasso', 'ElasticNet', 'SVR', 'DecisionTreeRegressor', 'RandomForestRegressor', 'GradientBoostingRegressor', 'XGBRegressor', 'LGBMRegressor', 'CatBoostRegressor', ], 'Classification': [ - 'LogisticRegression', 'SVC', 'DecisionTreeClassifier', 'RandomForestClassifier', 'GradientBoostingClassifier', 'XGBClassifier', 'LGBMClassifier', 'CatBoostClassifier', + 'LogisticRegression', 'BernoulliNB', 'MultinomialNB', 'GaussianNB', 'SVC', 'DecisionTreeClassifier', 'RandomForestClassifier', 'GradientBoostingClassifier', 'XGBClassifier', 'LGBMClassifier', 'CatBoostClassifier', ], 'Auto ML': [ - 'TPOTRegression', 'TPOTClassifier' + 'AutoSklearnRegressor', 'AutoSklearnClassifier', 'TPOTRegressor', 'TPOTClassifier' ], 'Clustering': [ 'KMeans', 'AgglomerativeClustering', 'GaussianMixture', 'DBSCAN', ], 'Dimension Reduction': [ - 'PCA', 'LinearDiscriminantAnalysis', 'TruncatedSVD', 'NMF' + 'PCA', 'LinearDiscriminantAnalysis', 'TruncatedSVD', 'NMF', 'TSNE' ], 'Data Preparation': [ /** Encoding */ 'OneHotEncoder', 'LabelEncoder', 'OrdinalEncoder', 'TargetEncoder', 'SMOTE', /** Scaling */ - 'StandardScaler', 'RobustScaler', 'MinMaxScaler', 'Normalizer', 'FunctionTransformer' + 'StandardScaler', 'RobustScaler', 'MinMaxScaler', 'Normalizer', 'FunctionTransformer', 'PolynomialFeatures' ] }; diff --git a/js/com/com_generatorV2.js b/js/com/com_generatorV2.js index 05da2e0b..d699e1f0 100644 --- a/js/com/com_generatorV2.js +++ b/js/com/com_generatorV2.js @@ -11,8 +11,9 @@ define([ 'vp_base/js/com/com_util', 'vp_base/js/com/com_makeDom', - 'vp_base/js/com/component/SuggestInput' -], function (com_util, com_makeDom, SuggestInput) { + 'vp_base/js/com/component/SuggestInput', + 'vp_base/js/com/component/VarSelector2' +], function (com_util, com_makeDom, SuggestInput, VarSelector2) { /** * show result after code executed */ @@ -37,11 +38,11 @@ define([ 'col_select': 'Select Column', 'textarea': 'Input textarea', 'input_number': 'Input number', - 'input': 'Input text' + 'input_text': 'Input text', + 'input': 'Input value' } const _VP_BOOL_OPTIONS = [ - { label: 'Default', value: '' }, { label: 'True', value: 'True' }, { label: 'False', value: 'False' } ] @@ -214,6 +215,8 @@ define([ let value = state[obj.name]; if (value == undefined) { value = ''; + } else { + obj.value = value; } // create as component type switch (componentType) { @@ -248,23 +251,15 @@ define([ content = renderTabBlock(pageThis, obj, state); break; case 'bool_checkbox': - // True False select box - var select = $(``); - select.append($('')) - .append($('')); - content = select; - break; case 'bool_select': - var optSlct = $('').attr({ - 'class':'vp-select option-select vp-state', - 'id':obj.name - }); + // True False select box + var optSlct = $(``); _VP_BOOL_OPTIONS.forEach((opt, idx) => { - var option = $(``).attr({ + var option = $(``).attr({ // 'id':opt, 'index':obj.index, 'name':obj.name, - 'value':opt.value + 'value':(obj.default==opt.value?'':opt.value) }); // cell metadata test if (value != undefined) { @@ -284,26 +279,26 @@ define([ 'class':'vp-select option-select vp-state', 'id':obj.name }); - // if required, no default option - if (obj.required != true) { - $(optSlct).append($('')); - } obj.options.forEach((opt, idx, arr) => { var label = (obj.options_label != undefined? obj.options_label[idx]:opt); + let isDefault = false; + if (obj.required != true && obj.default != undefined && obj.default == opt) { + isDefault = true; + label += ' (default)'; + } var option = $(``).attr({ // 'id':opt, 'index':obj.index, 'name':obj.name, - 'value':opt + 'value':(isDefault? '': opt) }); - // cell metadata test - if (value != undefined) { + // saved data + if ((value == opt) + || ((value == undefined || value == '') && isDefault)) { // set as saved value - if (value == opt) { - $(option).attr({ - 'selected':'selected' - }); - } + $(option).attr({ + 'selected':'selected' + }); } optSlct.append(option); }); @@ -322,7 +317,7 @@ define([ suggestInput.addClass('vp-input vp-state'); suggestInput.setSuggestList(function() { return obj.options; }); suggestInput.setNormalFilter(false); - suggestInput.setValue($(pageThis.wrapSelector('#' + obj.name)).val()); + suggestInput.setValue(value); suggestInput.setSelectEvent(function(selectedValue) { // trigger change $(pageThis.wrapSelector('#' + obj.name)).val(selectedValue); @@ -452,7 +447,7 @@ define([ suggestInput.addClass('vp-input vp-state'); suggestInput.setSuggestList(function() { return varList; }); suggestInput.setNormalFilter(false); - suggestInput.setValue($(divTag + ' #' + obj.name).val()); + suggestInput.setValue(defaultValue); suggestInput.setSelectEvent(function(selectedValue) { // trigger change $(divTag + ' #' + obj.name).val(selectedValue); diff --git a/js/com/com_interface.js b/js/com/com_interface.js index e19e6167..e5f05e13 100644 --- a/js/com/com_interface.js +++ b/js/com/com_interface.js @@ -49,6 +49,45 @@ define([ com_util.renderSuccessMessage('Your code has been executed'); } + + /** + * Insert multiple cells + * @param {String} type + * @param {Array} commands + * @param {boolean} exec + * @param {int} sigNum + */ + var insertCells = function(type, commands, exec=true, sigNum=-1) { + var selectedIndex = getSelectedCell(); + var targetCell = Jupyter.notebook.insert_cell_below(type, selectedIndex); + + commands && commands.forEach((command, idx) => { + // Add signature + if (type == 'code' && sigNum >= 0) { + command = com_util.formatString('# VisualPython [{0}] - {1}\n', sigNum, idx + 1) + command + } + targetCell.set_text(command); + Jupyter.notebook.select_next(); + if (exec) { + switch (type) { + case "markdown": + targetCell.render(); + break; + case "code": + default: + targetCell.execute(); + } + } + + selectedIndex = getSelectedCell(); + targetCell = Jupyter.notebook.insert_cell_below(type, selectedIndex); + }); + + // move to executed cell + Jupyter.notebook.scroll_to_cell(Jupyter.notebook.get_selected_index()); + + com_util.renderSuccessMessage('Your code has been executed'); + } var enableOtherShortcut = function() { vpLog.display(VP_LOG_TYPE.DEVELOP, 'enable short cut'); @@ -62,6 +101,7 @@ define([ return { insertCell: insertCell, + insertCells: insertCells, enableOtherShortcut: enableOtherShortcut, disableOtherShortcut: disableOtherShortcut, diff --git a/js/com/com_util.js b/js/com/com_util.js index 8533d38b..d63e5c7f 100644 --- a/js/com/com_util.js +++ b/js/com/com_util.js @@ -230,6 +230,12 @@ define([ return String(text).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); } + var optionToLabel = function(label) { + label = label.replaceAll('_', ' '); + label = label.charAt(0).toUpperCase() + label.slice(1); + return label; + } + return { getUUID: getUUID, loadCss: loadCss, @@ -238,6 +244,7 @@ define([ addVariable: addVariable, formatString: formatString, convertToStr: convertToStr, + optionToLabel: optionToLabel, removeHeadScript: removeHeadScript, renderModal: renderModal, diff --git a/js/com/component/InstanceEditor.js b/js/com/component/InstanceEditor.js index c3d78f35..ee3daf02 100644 --- a/js/com/component/InstanceEditor.js +++ b/js/com/component/InstanceEditor.js @@ -1,5 +1,3 @@ -const { param } = require("jquery"); - define([ 'css!vp_base/css/component/instanceEditor.css', 'vp_base/js/com/com_String', diff --git a/js/com/component/LibraryComponent.js b/js/com/component/LibraryComponent.js index 97b66247..fce95286 100644 --- a/js/com/component/LibraryComponent.js +++ b/js/com/component/LibraryComponent.js @@ -72,7 +72,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { $(tag).val(savedValue); break; } @@ -100,7 +100,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { newValue = $(tag).val(); break; } diff --git a/js/com/component/ModelEditor.js b/js/com/component/ModelEditor.js new file mode 100644 index 00000000..a147bdb2 --- /dev/null +++ b/js/com/component/ModelEditor.js @@ -0,0 +1,616 @@ +define([ + 'css!vp_base/css/component/instanceEditor.css', + 'vp_base/js/com/com_String', + 'vp_base/js/com/com_util', + 'vp_base/js/com/com_generatorV2', + 'vp_base/js/com/component/Component', + 'vp_base/js/com/component/SuggestInput' +], function(insCss, com_String, com_util, com_generator, Component, SuggestInput) { + + // temporary const + const VP_INS_BOX = 'vp-ins-box'; + const VP_INS_SELECT_CONTAINER = 'vp-ins-select-container'; + const VP_INS_SELECT_TITLE = 'vp-ins-select-title'; + const VP_INS_SEARCH = 'vp-ins-search'; + const VP_INS_TYPE = 'vp-ins-type'; + const VP_INS_SELECT_BOX = 'vp-ins-select-box'; + const VP_INS_SELECT_LIST = 'vp-ins-select-list'; + const VP_INS_SELECT_ITEM = 'vp-ins-select-item'; + + const VP_INS_PARAMETER_BOX = 'vp-ins-parameter-box'; + const VP_INS_PARAMETER = 'vp-ins-parameter'; + + class ModelEditor extends Component { + constructor(pageThis, targetId, containerId) { + super(null, { pageThis: pageThis, targetId: targetId, containerId: containerId }); + } + + _init() { + super._init(); + + this.pageThis = this.state.pageThis; + this.targetId = this.state.targetId; + this.containerId = this.state.containerId; + + let modelEditorType = ''; + let modelEditorName = ''; + if (this.pageThis.state['modelEditorType'] == undefined) { + modelEditorType = ''; + } + if (this.pageThis.state['modelEditorName'] == undefined) { + modelEditorName = ''; + } + + this.state = { + modelEditorType: modelEditorType, + modelEditorName: modelEditorName, + action: {}, + info: {}, + config: {}, + ...this.state + } + + this.loaded = false; + } + + render() { + ; + } + + getModelCategory(modelType) { + let mlDict = vpConfig.getMLDataDict(); + let keys = Object.keys(mlDict); + let modelCategory = ''; + for (let i = 0; i < keys.length; i++) { + let key = keys[i]; + if (mlDict[key].includes(modelType)) { + modelCategory = key; + break; + } + } + return modelCategory; + } + + getAction(modelType) { + let category = this.getModelCategory(modelType); + let defaultActions = { + 'fit': { + name: 'fit', + code: '${model}.fit(${featureData}, ${targetData})', + description: 'Perform modeling from features, or distance matrix.', + options: [ + { name: 'featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'X_train' }, + { name: 'targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'y_train' } + ] + }, + 'predict': { + name: 'predict', + code: '${allocatePredict} = ${model}.predict(${featureData})', + description: 'Predict the closest target data X belongs to.', + options: [ + { name: 'featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'X_test' }, + { name: 'allocatePredict', label: 'Allocate to', component: ['input'], placeholder: 'New variable', default: 'pred' } + ] + }, + 'predict_proba': { + name: 'predict_proba', + code: '${allocatePredict} = ${model}.predict_proba(${featureData})', + description: 'Predict class probabilities for X.', + options: [ + { name: 'featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'X_test' }, + { name: 'allocatePredict', label: 'Allocate to', component: ['input'], placeholder: 'New variable', default: 'pred' } + ] + }, + 'transform': { + name: 'transform', + code: '${allocateTransform} = ${model}.transform(${featureData})', + description: 'Apply dimensionality reduction to X.', + options: [ + { name: 'featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'X' }, + { name: 'allocateTransform', label: 'Allocate to', component: ['input'], placeholder: 'New variable' } + ] + } + }; + let actions = {}; + switch (category) { + case 'Data Preparation': + actions = { + 'fit': { + name: 'fit', + code: '${model}.fit(${featureData})', + description: 'Fit Encoder/Scaler to X.', + options: [ + { name: 'featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'X' } + ] + }, + 'fit_transform': { + name: 'fit_transform', + code: '${allocateTransform} = ${model}.fit_transform(${featureData})', + description: 'Fit Encoder/Scaler to X, then transform X.', + options: [ + { name: 'featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'X' }, + { name: 'allocateTransform', label: 'Allocate to', component: ['input'], placeholder: 'New variable' } + ] + }, + 'transform': { + ...defaultActions['transform'], + description: 'Transform labels to normalized encoding.' + }, + 'inverse_transform': { + name: 'inverse_transform', + code: '${allocateInverse} = ${model}.inverse_transform(${featureData})', + description: 'Transform binary labels back to multi-class labels.', + options: [ + { name: 'featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'X_train' }, + { name: 'allocateInverse', label: 'Allocate to', component: ['input'], placeholder: 'New variable' } + ] + } + } + break; + case 'Regression': + actions = { + 'fit': defaultActions['fit'], + 'predict': defaultActions['predict'], + } + break; + case 'Classification': + actions = { + 'fit': defaultActions['fit'], + 'predict': defaultActions['predict'], + 'predict_proba': defaultActions['predict_proba'], + } + if (['LogisticRegression', 'SVC', 'GradientBoostingClassifier'].includes(modelType)) { + actions = { + ...actions, + 'decision_function': { + name: 'decision_function', + code: '${allocateScore} = ${model}.decision_function(${featureData})', + description: 'Compute the decision function of X.', + options: [ + { name: 'featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'X' }, + { name: 'allocateScore', label: 'Allocate to', component: ['input'], placeholder: 'New variable' } + ] + } + } + } + break; + case 'Auto ML': + actions = { + 'fit': defaultActions['fit'], + 'predict': defaultActions['predict'] + } + if (modelType == 'TPOTClassifier') { + actions = { + ...actions, + 'predict_proba': defaultActions['predict_proba'] + } + } + break; + case 'Clustering': + if (modelType == 'AgglomerativeClustering' + || modelType == 'DBSCAN') { + actions = { + 'fit': defaultActions['fit'], + 'fit_predict': { + name: 'fit_predict', + code: '${allocatePredict} = ${model}.fit_predict(${featureData})', + description: 'Compute clusters from a data or distance matrix and predict labels.', + options: [ + { name: 'featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'X' }, + { name: 'allocatePredict', label: 'Allocate to', component: ['input'], placeholder: 'New variable', default: 'pred' } + ] + } + } + break; + } + actions = { + 'fit': defaultActions['fit'], + 'predict': defaultActions['predict'], + 'fit_predict': { + name: 'fit_predict', + code: '${allocatePredict} = ${model}.fit_predict(${featureData})', + description: 'Compute cluster centers and predict cluster index for each sample.', + options: [ + { name: 'featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'X' }, + { name: 'allocatePredict', label: 'Allocate to', component: ['input'], placeholder: 'New variable', default: 'pred' } + ] + } + } + if (modelType == 'KMeans') { + actions = { + ...actions, + 'fit_transform': { + name: 'fit_transform', + code: '${model}.fit_transform(${featureData})', + description: 'Compute clustering and transform X to cluster-distance space.', + options: [ + { name: 'featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'X_train' } + ] + }, + 'transform': { + name: 'transform', + code: '${allocateTransform} = ${model}.transform(${featureData})', + description: 'Transform X to a cluster-distance space.', + options: [ + { name: 'featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'X' }, + { name: 'allocateTransform', label: 'Allocate to', component: ['input'], placeholder: 'New variable' } + ] + } + } + } + break; + case 'Dimension Reduction': + if (modelType == 'TSNE') { + actions = { + 'fit': defaultActions['fit'], + 'fit_transform': { + name: 'fit_transform', + code: '${model}.fit_transform(${featureData})', + description: 'Fit X into an embedded space and return that transformed output.', + options: [ + { name: 'featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'X_train' } + ] + } + } + break; + } + actions = { + 'fit': defaultActions['fit'], + 'transform': defaultActions['transform'], + } + break; + } + return actions; + } + + getInfo(modelType) { + let category = this.getModelCategory(modelType); + let infos = {}; + let defaultInfos = { + 'score': { + name: 'score', + code: '${model}.score(${featureData}, {targetData})', + description: '', + options: [ + { name: 'featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'X' }, + { name: 'targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'y' } + ] + }, + 'cross_val_score': { + name: 'cross_val_score', + import: 'from sklearn.model_selection import cross_val_score', + code: '${allocateScore} = cross_val_score(${model}, ${featureData}, ${targetData}${scoring}${cv})', + description: 'Evaluate a score by cross-validation.', + options: [ + { name: 'featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'X' }, + { name: 'targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'y' }, + { name: 'scoring', component: ['input'], usePair: true }, + { name: 'cv', component: ['input'], usePair: true }, + { name: 'allocateScore', label: 'Allocate to', component: ['input'], placeholder: 'New variable' } + ] + }, + 'get_params': { + name: 'get_params', + code: '${allocateParam} = ${model}.get_params(${deep})', + description: 'Get parameters for this estimator.', + options: [ + { name: 'deep', component: ['bool_select'], default: 'True', usePair: true }, + { name: 'allocateParam', component: ['input'] } + ] + }, + 'permutation_importance': { + name: 'permutation_importance', + import: 'from sklearn.inspection import permutation_importance', + code: '${allocateImportance} = permutation_importance(${model}, ${featureData}, ${targetData}${scoring}${random_state}${etc})', + description: 'Permutation importance for feature evaluation.', + options: [ + { name: 'featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'X_train' }, + { name: 'targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], default: 'y_train' }, + { name: 'scoring', component: ['input'], usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true }, + { name: 'allocateImportance', label: 'Allocate to', component: ['input'], placeholder: 'New variable' } + ] + } + } + switch (category) { + case 'Data Preparation': + infos = { + 'get_params': defaultInfos['get_params'] + } + break; + case 'Regression': + infos = { + 'score': { + ...defaultInfos['score'], + description: 'Return the coefficient of determination of the prediction.' + }, + 'cross_val_score': defaultInfos['cross_val_score'], + 'permutation_importance': defaultInfos['permutation_importance'], + 'Coefficient': { + name: 'Coefficient', + code: '${allocateCoef} = ${model}.coef_', + options: [ + { name: 'allocateCoef', label: 'Allocate to', component: ['input'], placeholder: 'New variable' } + ] + }, + 'Intercept': { + name: 'Intercept', + code: '${allocateIntercept} = ${model}.intercept_', + options: [ + { name: 'allocateIntercept', label: 'Allocate to', component: ['input'], placeholder: 'New variable' } + ] + } + } + break; + case 'Classification': + infos = { + 'score': { + ...defaultInfos['score'], + description: 'Return the mean accuracy on the given test data and labels.' + }, + 'cross_val_score': defaultInfos['cross_val_score'], + 'permutation_importance': defaultInfos['permutation_importance'] + } + break; + case 'Auto ML': + break; + case 'Clustering': + infos = { + // 'Size of clusters': { + // name: 'Size of clusters', + // code: "print(f'Size of clusters: {np.bincount(pred)}')", // FIXME: model.cluster_centers_ / use model info or hide it + // options: [] + // } + } + + if (modelType == 'KMeans') { + infos = { + ...infos, + 'cluster_centers_': { + name: 'cluster_centers', + code: '${allocateCenters} = ${model}.cluster_centers_', + description: 'Coordinates of cluster centers.', + options: [ + { name: 'allocateCenters', label: 'Allocate to', component: ['input'], placeholder: 'New variable' } + ] + } + } + } + + if (modelType == 'AgglomerativeClustering') { + infos = { + ...infos, + 'Dendrogram': { // FIXME: + name: 'Dendrogram', + code: "# import\nfrom scipy.cluster.hierarchy import dendrogram, ward\n\nlinkage_array = ward(${data})\ndendrogram(linkage_array, p=3, truncate_mode='level', no_labels=True)\nplt.show()", + description: 'Draw a dendrogram', + options: [ + { name: 'data', label: 'Data', component: ['var_select'], var_type: ['DataFrame']} + ] + } + } + } + break; + case 'Dimension Reduction': + if (modelType == 'PCA') { + infos = { + 'explained_variance_ratio_': { + name: 'explained_variance_ratio_', + code: '${allocateRatio} = ${model}.explained_variance_ratio_', + description: 'Percentage of variance explained by each of the selected components.', + options: [ + { name: 'allocateRatio', label: 'Allocate to', component: ['input'], placeholder: 'New variable' } + ] + } + } + } + break; + } + return infos; + } + + renderPage() { + var tag = new com_String(); + tag.appendFormatLine('
', VP_INS_BOX, this.uuid); // vp-select-base + + // Model Editor State (Saved state) + tag.appendFormatLine('', 'modelEditorType', this.state.modelEditorType); + tag.appendFormatLine('', 'modelEditorName', this.state.modelEditorName); + + tag.appendFormatLine('
', VP_INS_SELECT_CONTAINER, 'action'); + tag.appendFormatLine('
Action
', VP_INS_SELECT_TITLE); + + tag.appendFormatLine('
', 'position: relative;'); + tag.appendFormatLine('', VP_INS_SEARCH, 'attr'); + tag.appendFormatLine('', VP_INS_TYPE, 'action'); + tag.appendFormatLine('', 'fa fa-search', 'vp-ins-search-icon'); + tag.appendLine('
'); + + tag.appendFormatLine('
', VP_INS_SELECT_BOX, 'action'); + tag.appendFormatLine('
    ', VP_INS_SELECT_LIST, 'action'); + tag.appendLine('
'); + tag.appendLine('
'); // VP_INS_SELECT_BOX + tag.appendLine('
'); // VP_INS_SELECT_CONTAINER + + tag.appendFormatLine('
', VP_INS_SELECT_CONTAINER, 'info'); + tag.appendFormatLine('
Info
', VP_INS_SELECT_TITLE); + + tag.appendFormatLine('
', 'position: relative;'); + tag.appendFormatLine('', VP_INS_SEARCH, 'method'); + tag.appendFormatLine('', VP_INS_TYPE, 'info'); + tag.appendFormatLine('', 'fa fa-search', 'vp-ins-search-icon'); + tag.appendLine('
'); + + tag.appendFormatLine('
', VP_INS_SELECT_BOX, 'info'); + tag.appendFormatLine('
    ', VP_INS_SELECT_LIST, 'info'); + tag.appendLine('
'); + tag.appendLine('
'); // VP_INS_SELECT_BOX + tag.appendLine('
'); // VP_INS_SELECT_CONTAINER + + tag.appendFormatLine('
Options
', VP_INS_SELECT_TITLE); + tag.appendFormatLine('
', VP_INS_PARAMETER_BOX); + tag.appendLine('
'); // VP_INS_BOX END + + $(this.pageThis.wrapSelector('#' + this.containerId)).html(tag.toString()); + + return tag.toString(); + } + + reload() { + this.renderPage(); + + let targetTag = $(this.pageThis.wrapSelector('#' + this.targetId)); + let model = $(targetTag).val(); + let modelType = $(targetTag).find('option:selected').data('type'); + + let actions = this.getAction(modelType); + let infos = this.getInfo(modelType); + this.state.action = { ...actions }; + this.state.info = { ...infos }; + + var actListTag = new com_String(); + var infoListTag = new com_String(); + + Object.keys(actions).forEach(actKey => { + actListTag.appendFormatLine('
  • {4}
  • ', + VP_INS_SELECT_ITEM, actKey, 'action', actions[actKey].description, actKey); + }); + Object.keys(infos).forEach(infoKey => { + infoListTag.appendFormatLine('
  • {4}
  • ', + VP_INS_SELECT_ITEM, infoKey, 'info', infos[infoKey].description, infoKey); + }); + + $(this.wrapSelector('.' + VP_INS_SELECT_LIST + '.action')).html(actListTag.toString()); + $(this.wrapSelector('.' + VP_INS_SELECT_LIST + '.info')).html(infoListTag.toString()); + + let that = this; + // action search suggest + var suggestInput = new SuggestInput(); + suggestInput.addClass('vp-input action'); + suggestInput.addClass(VP_INS_SEARCH); + suggestInput.setPlaceholder("Search Action"); + suggestInput.setSuggestList(function () { return Object.keys(actions); }); + suggestInput.setSelectEvent(function (value, item) { + $(this.wrapSelector()).val(value); + $(that.wrapSelector('.' + VP_INS_TYPE + '.action')).val(item.type); + + $(that.pageThis.wrapSelector('#' + that.targetId)).trigger({ + type: "model_editor_selected", + varName: value, + varOptions: actions[value], + isMethod: false + }); + }); + $(that.wrapSelector('.' + VP_INS_SEARCH + '.action')).replaceWith(function () { + return suggestInput.toTagString(); + }); + + // info search suggest + suggestInput = new SuggestInput(); + suggestInput.addClass('vp-input info'); + suggestInput.addClass(VP_INS_SEARCH); + suggestInput.setPlaceholder("Search info"); + suggestInput.setSuggestList(function () { return Object.keys(infos); }); + suggestInput.setSelectEvent(function (value, item) { + $(this.wrapSelector()).val(value); + $(that.wrapSelector('.' + VP_INS_TYPE + '.info')).val(item.type); + + $(that.pageThis.wrapSelector('#' + that.targetId)).trigger({ + type: "model_editor_selected", + varName: value, + varOptions: infos[value], + isMethod: true + }); + }); + $(that.wrapSelector('.' + VP_INS_SEARCH + '.info')).replaceWith(function () { + return suggestInput.toTagString(); + }); + + // bind event + this._bindEvent(); + + // load once on initializing page + if (this.loaded == false) { + let { modelEditorType, modelEditorName } = this.pageThis.state; + if (modelEditorType != '' && modelEditorName != '') { + // render option page for saved state + that.renderOptionPage(modelEditorType, modelEditorName); + } + // set loaded true + this.loaded = true; + } + } + + renderOptionPage(type, name) { + if (this.state[type] != undefined && this.state[type][name] != undefined) { + let config = this.state[type][name]; + let optBox = new com_String(); + // render tag + config && config.options && config.options.forEach(opt => { + let label = opt.name; + if (opt.label != undefined) { + label = opt.label; + } + // fix label + label = com_util.optionToLabel(label); + optBox.appendFormatLine('' + , opt.name, opt.name, label); + let content = com_generator.renderContent(this, opt.component[0], opt, this.pageThis.state); + optBox.appendLine(content[0].outerHTML); + }); + // replace option box + $(this.wrapSelector('.' + VP_INS_PARAMETER_BOX)).html(optBox.toString()); + + this.state.config = config; + + // add selection + $(this.wrapSelector('.' + VP_INS_SELECT_ITEM)).removeClass('selected'); + let typeClass = '.' + VP_INS_SELECT_LIST + '.' + type; + let nameClass = '.' + VP_INS_SELECT_ITEM + '[data-var-name="' + name + '"]'; + $(this.wrapSelector(typeClass + ' ' + nameClass)).addClass('selected'); + // set state + $(this.wrapSelector('#modelEditorType')).val(type); + $(this.wrapSelector('#modelEditorName')).val(name); + this.pageThis.state.modelEditorType = type; + this.pageThis.state.modelEditorName = name; + } + } + + _bindEvent() { + super._bindEvent(); + let that = this; + + $(this.wrapSelector('.' + VP_INS_SELECT_ITEM)).on('click', function() { + let name = $(this).data('var-name'); + let type = $(this).data('var-type'); + + that.renderOptionPage(type, name); + }); + } + + show() { + $(this.wrapSelector()).show(); + this.reload(); + } + + hide() { + $(this.wrapSelector()).hide(); + } + + getCode(replaceDict={}) { + let code = new com_String(); + if (this.state.config.import != undefined) { + code.appendLine(this.state.config.import); + code.appendLine(); + } + let modelCode = com_generator.vp_codeGenerator(this.pageThis, this.state.config, this.pageThis.state); + Object.keys(replaceDict).forEach(key => { + modelCode = modelCode.replace(key, replaceDict[key]); + }); + code.append(modelCode); + return code.toString(); + } + } + + return ModelEditor; +}); \ No newline at end of file diff --git a/js/com/component/NumpyComponent.js b/js/com/component/NumpyComponent.js index fab327db..09d50026 100644 --- a/js/com/component/NumpyComponent.js +++ b/js/com/component/NumpyComponent.js @@ -79,7 +79,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { $(tag).val(savedValue); break; } @@ -107,7 +107,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { newValue = $(tag).val(); break; } diff --git a/js/com/component/PopupComponent.js b/js/com/component/PopupComponent.js index af8c8431..64275051 100644 --- a/js/com/component/PopupComponent.js +++ b/js/com/component/PopupComponent.js @@ -269,7 +269,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(this).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { newValue = $(this).val(); break; } @@ -541,7 +541,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { newValue = $(tag).val(); break; } @@ -586,7 +586,12 @@ define([ blockNumber = block.blockNumber; } if (addcell) { - com_interface.insertCell(mode, code, execute, blockNumber); + if (Array.isArray(code)) { + // insert cells if it's array of codes + com_interface.insertCells(mode, code, execute, blockNumber); + } else { + com_interface.insertCell(mode, code, execute, blockNumber); + } } return code; } @@ -693,7 +698,13 @@ define([ openView(viewType) { if (viewType == 'code') { var code = this.generateCode(); - this.cmCodeview.setValue(code); + let codeText = ''; + if (Array.isArray(code)) { + codeText = code.join('\n'); + } else { + codeText = code; + } + this.cmCodeview.setValue(codeText); this.cmCodeview.save(); var that = this; diff --git a/js/m_apps/Chart.js b/js/m_apps/Chart.js index 7658bab9..76ed858e 100644 --- a/js/m_apps/Chart.js +++ b/js/m_apps/Chart.js @@ -173,7 +173,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { $(tag).val(savedValue); break; } diff --git a/js/m_ml/AutoML.js b/js/m_ml/AutoML.js index 4f0548e5..24934a30 100644 --- a/js/m_ml/AutoML.js +++ b/js/m_ml/AutoML.js @@ -15,14 +15,14 @@ define([ 'text!vp_base/html/m_ml/model.html!strip', 'vp_base/js/com/com_util', - 'vp_base/js/com/com_Const', + '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/InstanceEditor' -], function(msHtml, com_util, com_Const, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, InstanceEditor) { + 'vp_base/js/com/component/ModelEditor' +], function(msHtml, com_util, com_interface, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, ModelEditor) { /** * AutoML @@ -40,7 +40,7 @@ define([ userOption: '', featureData: 'X_train', targetData: 'y_train', - allocateTo: 'model', + allocateToCreation: 'model', // model selection model: '', method: '', @@ -50,11 +50,8 @@ define([ this.modelConfig = ML_LIBRARIES; this.modelTypeList = { - // 'Regression': ['ln-rgs', 'sv-rgs', 'dt-rgs', 'rf-rgs', 'gbm-rgs', 'xgb-rgs', 'lgbm-rgs', 'cb-rgs'], - // 'Classfication': ['lg-rgs', 'sv-clf', 'dt-clf', 'rf-clf', 'gbm-clf', 'xgb-clf', 'lgbm-clf', 'cb-clf'], - 'Auto ML': ['tpot-rgs', 'tpot-clf'], - // 'Clustering': ['k-means', 'agg-cls', 'gaus-mix', 'dbscan'], - // 'Dimension Reduction': ['pca', 'lda', 'svd', 'nmf'] + 'Regression': ['auto-sklearn-rgs', 'tpot-rgs'], + 'Classification': ['auto-sklearn-clf', 'tpot-clf'] } @@ -94,6 +91,11 @@ define([ com_interface.insertCell('code', config.install); } }); + + // change model + $(this.wrapSelector('#model')).on('change', function() { + that.modelEditor.reload(); + }) } templateForBody() { @@ -171,7 +173,7 @@ define([ that.state.model = $(that.wrapSelector('#model')).val(); } - that.insEditor.show(); + that.modelEditor.show(); }); //================================================================ @@ -187,7 +189,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { $(tag).val(value); break; } @@ -215,7 +217,7 @@ define([ // render tag config.options.forEach(opt => { optBox.appendFormatLine('' - , opt.name, opt.name, opt.name); + , 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); }); @@ -229,13 +231,12 @@ define([ render() { super.render(); - // Instance Editor - this.insEditor = new InstanceEditor(this, "model", "instanceEditor"); - this.insEditor.show(); + // Model Editor + this.modelEditor = new ModelEditor(this, "model", "instanceEditor"); } generateCode() { - let { modelControlType, modelType, userOption, featureData, targetData, allocateTo } = this.state; + let { modelControlType, modelType, userOption, allocateToCreation, model } = this.state; let code = new com_String(); if (modelControlType == 'creation') { /** @@ -251,15 +252,14 @@ define([ // model code let modelCode = config.code; modelCode = com_generator.vp_codeGenerator(this, config, this.state, userOption); - code.appendFormat('{0} = {1}', allocateTo, modelCode); + code.appendFormat('{0} = {1}', allocateToCreation, modelCode); } else { /** * Model Selection * --- * ... */ - - + code.append(this.modelEditor.getCode({'${model}': model})); } return code.toString(); diff --git a/js/m_ml/Classification.js b/js/m_ml/Classification.js index dc97f0e7..d45cf083 100644 --- a/js/m_ml/Classification.js +++ b/js/m_ml/Classification.js @@ -15,14 +15,14 @@ define([ 'text!vp_base/html/m_ml/model.html!strip', 'vp_base/js/com/com_util', - 'vp_base/js/com/com_Const', + '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/InstanceEditor' -], function(msHtml, com_util, com_Const, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, InstanceEditor) { + 'vp_base/js/com/component/ModelEditor' +], function(msHtml, com_util, com_interface, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, ModelEditor) { /** * Classification @@ -40,7 +40,7 @@ define([ userOption: '', featureData: 'X_train', targetData: 'y_train', - allocateTo: 'model', + allocateToCreation: 'model', // model selection model: '', method: '', @@ -50,11 +50,7 @@ define([ this.modelConfig = ML_LIBRARIES; this.modelTypeList = { - // 'Regression': ['ln-rgs', 'sv-rgs', 'dt-rgs', 'rf-rgs', 'gbm-rgs', 'xgb-rgs', 'lgbm-rgs', 'cb-rgs'], - 'Classfication': ['lg-rgs', 'sv-clf', 'dt-clf', 'rf-clf', 'gbm-clf', 'xgb-clf', 'lgbm-clf', 'cb-clf'], - // 'Auto ML': ['tpot-rgs', 'tpot-clf'], - // 'Clustering': ['k-means', 'agg-cls', 'gaus-mix', 'dbscan'], - // 'Dimension Reduction': ['pca', 'lda', 'svd', 'nmf'] + 'Classfication': ['lg-rgs', 'bern-nb', 'mulnom-nb', 'gaus-nb', 'sv-clf', 'dt-clf', 'rf-clf', 'gbm-clf', 'xgb-clf', 'lgbm-clf', 'cb-clf'], } @@ -94,6 +90,11 @@ define([ com_interface.insertCell('code', config.install); } }); + + // change model + $(this.wrapSelector('#model')).on('change', function() { + that.modelEditor.reload(); + }) } templateForBody() { @@ -171,7 +172,7 @@ define([ that.state.model = $(that.wrapSelector('#model')).val(); } - that.insEditor.show(); + that.modelEditor.show(); }); //================================================================ @@ -187,7 +188,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { $(tag).val(value); break; } @@ -215,7 +216,7 @@ define([ // render tag config.options.forEach(opt => { optBox.appendFormatLine('' - , opt.name, opt.name, opt.name); + , 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); }); @@ -229,13 +230,12 @@ define([ render() { super.render(); - // Instance Editor - this.insEditor = new InstanceEditor(this, "model", "instanceEditor"); - this.insEditor.show(); + // Model Editor + this.modelEditor = new ModelEditor(this, "model", "instanceEditor"); } generateCode() { - let { modelControlType, modelType, userOption, featureData, targetData, allocateTo } = this.state; + let { modelControlType, modelType, userOption, allocateToCreation, model } = this.state; let code = new com_String(); if (modelControlType == 'creation') { /** @@ -251,15 +251,14 @@ define([ // model code let modelCode = config.code; modelCode = com_generator.vp_codeGenerator(this, config, this.state, userOption); - code.appendFormat('{0} = {1}', allocateTo, modelCode); + code.appendFormat('{0} = {1}', allocateToCreation, modelCode); } else { /** * Model Selection * --- * ... */ - - + code.append(this.modelEditor.getCode({'${model}': model})); } return code.toString(); diff --git a/js/m_ml/Clustering.js b/js/m_ml/Clustering.js index 9d609a88..f7f65976 100644 --- a/js/m_ml/Clustering.js +++ b/js/m_ml/Clustering.js @@ -15,14 +15,14 @@ define([ 'text!vp_base/html/m_ml/model.html!strip', 'vp_base/js/com/com_util', - 'vp_base/js/com/com_Const', + '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/InstanceEditor' -], function(msHtml, com_util, com_Const, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, InstanceEditor) { + 'vp_base/js/com/component/ModelEditor' +], function(msHtml, com_util, com_interface, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, ModelEditor) { /** * Clustering @@ -40,7 +40,7 @@ define([ userOption: '', featureData: 'X_train', targetData: 'y_train', - allocateTo: 'model', + allocateToCreation: 'model', // model selection model: '', method: '', @@ -94,6 +94,11 @@ define([ com_interface.insertCell('code', config.install); } }); + + // change model + $(this.wrapSelector('#model')).on('change', function() { + that.modelEditor.reload(); + }) } templateForBody() { @@ -171,7 +176,7 @@ define([ that.state.model = $(that.wrapSelector('#model')).val(); } - that.insEditor.show(); + that.modelEditor.show(); }); //================================================================ @@ -187,7 +192,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { $(tag).val(value); break; } @@ -215,7 +220,7 @@ define([ // render tag config.options.forEach(opt => { optBox.appendFormatLine('' - , opt.name, opt.name, opt.name); + , 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); }); @@ -229,13 +234,12 @@ define([ render() { super.render(); - // Instance Editor - this.insEditor = new InstanceEditor(this, "model", "instanceEditor"); - this.insEditor.show(); + // Model Editor + this.modelEditor = new ModelEditor(this, "model", "instanceEditor"); } generateCode() { - let { modelControlType, modelType, userOption, featureData, targetData, allocateTo } = this.state; + let { modelControlType, modelType, userOption, allocateToCreation, model } = this.state; let code = new com_String(); if (modelControlType == 'creation') { /** @@ -251,15 +255,14 @@ define([ // model code let modelCode = config.code; modelCode = com_generator.vp_codeGenerator(this, config, this.state, userOption); - code.appendFormat('{0} = {1}', allocateTo, modelCode); + code.appendFormat('{0} = {1}', allocateToCreation, modelCode); } else { /** * Model Selection * --- * ... */ - - + code.append(this.modelEditor.getCode({'${model}': model})); } return code.toString(); diff --git a/js/m_ml/DataPrep.js b/js/m_ml/DataPrep.js index 333fd0c7..46455668 100644 --- a/js/m_ml/DataPrep.js +++ b/js/m_ml/DataPrep.js @@ -15,14 +15,14 @@ define([ 'text!vp_base/html/m_ml/model.html!strip', 'vp_base/js/com/com_util', - 'vp_base/js/com/com_Const', + '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/InstanceEditor' -], function(msHtml, com_util, com_Const, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, InstanceEditor) { + 'vp_base/js/com/component/ModelEditor' +], function(msHtml, com_util, com_interface, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, ModelEditor) { /** * DataPrep @@ -40,7 +40,7 @@ define([ userOption: '', featureData: 'X_train', targetData: 'y_train', - allocateTo: 'model', + allocateToCreation: 'model', // model selection model: '', method: '', @@ -51,13 +51,7 @@ define([ this.modelTypeList = { 'Encoding': ['prep-onehot', 'prep-label', 'prep-ordinal', 'prep-target', 'prep-smote'], - 'Scaling': ['prep-standard', 'prep-robust', 'prep-minmax', 'prep-normalizer', 'prep-func-trsfrm-log', 'prep-func-trsfrm-exp'] - - // 'Regression': ['ln-rgs', 'sv-rgs', 'dt-rgs', 'rf-rgs', 'gbm-rgs', 'xgb-rgs', 'lgbm-rgs', 'cb-rgs'], - // 'Classfication': ['lg-rgs', 'sv-clf', 'dt-clf', 'rf-clf', 'gbm-clf', 'xgb-clf', 'lgbm-clf', 'cb-clf'], - // 'Auto ML': ['tpot-rgs', 'tpot-clf'], - // 'Clustering': ['k-means', 'agg-cls', 'gaus-mix', 'dbscan'], - // 'Dimension Reduction': ['pca', 'lda', 'svd', 'nmf'] + 'Scaling': ['prep-standard', 'prep-robust', 'prep-minmax', 'prep-normalizer', 'prep-func-trsfrm-log', 'prep-func-trsfrm-exp', 'prep-poly-feat'] } @@ -97,6 +91,11 @@ define([ com_interface.insertCell('code', config.install); } }); + + // change model + $(this.wrapSelector('#model')).on('change', function() { + that.modelEditor.reload(); + }); } templateForBody() { @@ -174,7 +173,7 @@ define([ that.state.model = $(that.wrapSelector('#model')).val(); } - that.insEditor.show(); + that.modelEditor.show(); }); //================================================================ @@ -190,7 +189,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { $(tag).val(value); break; } @@ -218,14 +217,17 @@ define([ // render tag config.options.forEach(opt => { optBox.appendFormatLine('' - , opt.name, opt.name, opt.name); + , 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); + // show user option + if (config.code.includes('${etc}')) { + // render user option + optBox.appendFormatLine('', 'userOption', 'User option'); + optBox.appendFormatLine('', + 'userOption', 'key=value, ...', this.state.userOption); + } return optBox.toString(); } @@ -233,12 +235,11 @@ define([ super.render(); // Instance Editor - this.insEditor = new InstanceEditor(this, "model", "instanceEditor"); - this.insEditor.show(); + this.modelEditor = new ModelEditor(this, "model", "instanceEditor"); } generateCode() { - let { modelControlType, modelType, userOption, featureData, targetData, allocateTo } = this.state; + let { modelControlType, modelType, userOption, allocateToCreation, model } = this.state; let code = new com_String(); if (modelControlType == 'creation') { /** @@ -254,15 +255,14 @@ define([ // model code let modelCode = config.code; modelCode = com_generator.vp_codeGenerator(this, config, this.state, userOption); - code.appendFormat('{0} = {1}', allocateTo, modelCode); + code.appendFormat('{0} = {1}', allocateToCreation, modelCode); } else { /** * Model Selection * --- * ... */ - - + code.append(this.modelEditor.getCode({'${model}': model})); } return code.toString(); diff --git a/js/m_ml/DataSets.js b/js/m_ml/DataSets.js index cb480970..479bdf02 100644 --- a/js/m_ml/DataSets.js +++ b/js/m_ml/DataSets.js @@ -13,11 +13,14 @@ // [CLASS] DataSets //============================================================================ define([ + 'text!vp_base/html/m_ml/dataSets.html!strip', 'vp_base/js/com/com_util', 'vp_base/js/com/com_Const', 'vp_base/js/com/com_String', 'vp_base/js/com/component/PopupComponent', -], function(com_util, com_Const, com_String, PopupComponent) { + 'vp_base/js/com/com_generatorV2', + 'vp_base/data/m_ml/mlLibrary', +], function(dsHTML, com_util, com_Const, com_String, PopupComponent, com_generator, ML_LIBRARIES) { /** * DataSets @@ -29,15 +32,130 @@ define([ this.config.dataview = false; this.state = { - + loadType: 'load_boston', + userOption: '', + allocateTo: 'ldata', ...this.state } + + this.mlConfig = ML_LIBRARIES; + this.loadTypeList = { + 'Load Data': [ + 'load_boston', 'load_iris', 'load_diabetes', 'load_digits', 'load_linnerud', 'load_wine', 'load_breast_cancer' + ], + 'Create Data': [ + 'make_classification', 'make_blobs', 'make_circles', 'make_moons' + ] + } + + } + + _bindEvent() { + super._bindEvent(); + let that = this; + + // select model + $(this.wrapSelector('#loadType')).on('change', function() { + let loadType = $(this).val(); + that.state.loadType = loadType; + $(that.wrapSelector('.vp-data-option-box')).html(that.templateForOption(loadType)); + + // change allocateTo default variable name + if (that.loadTypeList['Load Data'].includes(loadType)) { + $(that.wrapSelector('#allocateTo')).val('ldata'); + that.state.allocateTo = 'ldata'; + } else { + $(that.wrapSelector('#allocateTo')).val('df'); + that.state.allocateTo = 'df'; + } + }); } templateForBody() { - return 'Data Set test'; + let page = $(dsHTML); + + let that = this; + // load types + let loadTypeTag = new com_String(); + Object.keys(this.loadTypeList).forEach(category => { + let optionTag = new com_String(); + that.loadTypeList[category].forEach(opt => { + let optConfig = that.mlConfig[opt]; + let selectedFlag = ''; + if (opt == that.state.modelType) { + selectedFlag = 'selected'; + } + optionTag.appendFormatLine('', + opt, selectedFlag, optConfig.name); + }) + loadTypeTag.appendFormatLine('{1}', + category, optionTag.toString()); + }); + $(page).find('#loadType').html(loadTypeTag.toString()); + + // render option page + $(page).find('.vp-data-option-box').html(this.templateForOption(this.state.loadType)); + + return page; } + templateForOption(loadType) { + let config = this.mlConfig[loadType]; + let state = this.state; + + let optBox = new com_String(); + // render tag + config.options.forEach(opt => { + optBox.appendFormatLine('' + , opt.name, opt.name, opt.name); + let content = com_generator.renderContent(this, opt.component[0], opt, state); + optBox.appendLine(content[0].outerHTML); + }); + + // show user option + if (config.code.includes('${etc}')) { + // render user option + optBox.appendFormatLine('', 'userOption', 'User option'); + optBox.appendFormatLine('', + 'userOption', 'key=value, ...', this.state.userOption); + } + return optBox.toString(); + } + + generateCode() { + let { loadType, userOption, allocateTo } = this.state; + let code = new com_String(); + let config = this.mlConfig[loadType]; + code.appendLine(config.import); + code.appendLine(); + + // model code + let modelCode = config.code; + modelCode = com_generator.vp_codeGenerator(this, config, this.state, userOption); + + let allocateToVar = allocateTo; + if (this.loadTypeList['Load Data'].includes(loadType)) { + code.appendFormatLine('{0} = {1}', allocateTo, modelCode); + code.appendLine("# Create DataFrame"); + code.appendFormatLine("df_{0} = pd.DataFrame(data={1}.data, columns={2}.feature_names)", allocateTo, allocateTo, allocateTo); + code.appendFormat("df_{0}['target'] = {1}.target", allocateTo, allocateTo); + allocateToVar = 'df_' + allocateTo; + } else { + code.appendFormatLine("_X, _y = {0}", modelCode); + code.appendLine("# Create DataFrame"); + code.appendLine("_feature_names = ['X{}'.format(i+1) for i in range(len(_X[0]))]"); + code.appendFormatLine("{0} = pd.DataFrame(data=_X, columns=_feature_names)", allocateTo); + code.appendFormat("{0}['target'] = _y", allocateTo); + } + + if (allocateToVar != '') { + code.appendLine(); + code.append(allocateToVar); + } + + + return code.toString(); + } } return DataSets; diff --git a/js/m_ml/DimensionReduction.js b/js/m_ml/DimensionReduction.js index 93ba2686..9f976a3d 100644 --- a/js/m_ml/DimensionReduction.js +++ b/js/m_ml/DimensionReduction.js @@ -15,14 +15,14 @@ define([ 'text!vp_base/html/m_ml/model.html!strip', 'vp_base/js/com/com_util', - 'vp_base/js/com/com_Const', + '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/InstanceEditor' -], function(msHtml, com_util, com_Const, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, InstanceEditor) { + 'vp_base/js/com/component/ModelEditor' +], function(msHtml, com_util, com_interface, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, ModelEditor) { /** * DimensionReduction @@ -40,7 +40,7 @@ define([ userOption: '', featureData: 'X_train', targetData: 'y_train', - allocateTo: 'model', + allocateToCreation: 'model', // model selection model: '', method: '', @@ -50,11 +50,7 @@ define([ this.modelConfig = ML_LIBRARIES; this.modelTypeList = { - // 'Regression': ['ln-rgs', 'sv-rgs', 'dt-rgs', 'rf-rgs', 'gbm-rgs', 'xgb-rgs', 'lgbm-rgs', 'cb-rgs'], - // 'Classfication': ['lg-rgs', 'sv-clf', 'dt-clf', 'rf-clf', 'gbm-clf', 'xgb-clf', 'lgbm-clf', 'cb-clf'], - // 'Auto ML': ['tpot-rgs', 'tpot-clf'], - // 'Clustering': ['k-means', 'agg-cls', 'gaus-mix', 'dbscan'], - 'Dimension Reduction': ['pca', 'lda', 'svd', 'nmf'] + 'Dimension Reduction': ['pca', 'lda', 'svd', 'nmf', 'tsne'] } @@ -94,6 +90,11 @@ define([ com_interface.insertCell('code', config.install); } }); + + // change model + $(this.wrapSelector('#model')).on('change', function() { + that.modelEditor.reload(); + }) } templateForBody() { @@ -171,7 +172,7 @@ define([ that.state.model = $(that.wrapSelector('#model')).val(); } - that.insEditor.show(); + that.modelEditor.show(); }); //================================================================ @@ -187,7 +188,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { $(tag).val(value); break; } @@ -215,7 +216,7 @@ define([ // render tag config.options.forEach(opt => { optBox.appendFormatLine('' - , opt.name, opt.name, opt.name); + , 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); }); @@ -229,13 +230,12 @@ define([ render() { super.render(); - // Instance Editor - this.insEditor = new InstanceEditor(this, "model", "instanceEditor"); - this.insEditor.show(); + // Model Editor + this.modelEditor = new ModelEditor(this, "model", "instanceEditor"); } generateCode() { - let { modelControlType, modelType, userOption, featureData, targetData, allocateTo } = this.state; + let { modelControlType, modelType, userOption, allocateToCreation, model } = this.state; let code = new com_String(); if (modelControlType == 'creation') { /** @@ -251,15 +251,14 @@ define([ // model code let modelCode = config.code; modelCode = com_generator.vp_codeGenerator(this, config, this.state, userOption); - code.appendFormat('{0} = {1}', allocateTo, modelCode); + code.appendFormat('{0} = {1}', allocateToCreation, modelCode); } else { /** * Model Selection * --- * ... */ - - + code.append(this.modelEditor.getCode({'${model}': model})); } return code.toString(); diff --git a/js/m_ml/Regression.js b/js/m_ml/Regression.js index 7a08dd68..b1e8d6c1 100644 --- a/js/m_ml/Regression.js +++ b/js/m_ml/Regression.js @@ -15,14 +15,14 @@ define([ 'text!vp_base/html/m_ml/model.html!strip', 'vp_base/js/com/com_util', - 'vp_base/js/com/com_Const', + '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/InstanceEditor' -], function(msHtml, com_util, com_Const, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, InstanceEditor) { + 'vp_base/js/com/component/ModelEditor' +], function(msHtml, com_util, com_interface, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, ModelEditor) { /** * Regression @@ -40,7 +40,7 @@ define([ userOption: '', featureData: 'X_train', targetData: 'y_train', - allocateTo: 'model', + allocateToCreation: 'model', // model selection model: '', method: '', @@ -50,11 +50,7 @@ define([ this.modelConfig = ML_LIBRARIES; this.modelTypeList = { - 'Regression': ['ln-rgs', 'sv-rgs', 'dt-rgs', 'rf-rgs', 'gbm-rgs', 'xgb-rgs', 'lgbm-rgs', 'cb-rgs'], - // 'Classfication': ['lg-rgs', 'sv-clf', 'dt-clf', 'rf-clf', 'gbm-clf', 'xgb-clf', 'lgbm-clf', 'cb-clf'], - // 'Auto ML': ['tpot-rgs', 'tpot-clf'], - // 'Clustering': ['k-means', 'agg-cls', 'gaus-mix', 'dbscan'], - // 'Dimension Reduction': ['pca', 'lda', 'svd', 'nmf'] + 'Regression': ['ln-rgs', 'ridge', 'lasso', 'elasticnet', 'sv-rgs', 'dt-rgs', 'rf-rgs', 'gbm-rgs', 'xgb-rgs', 'lgbm-rgs', 'cb-rgs'], } @@ -94,6 +90,11 @@ define([ com_interface.insertCell('code', config.install); } }); + + // change model + $(this.wrapSelector('#model')).on('change', function() { + that.modelEditor.reload(); + }) } templateForBody() { @@ -171,7 +172,7 @@ define([ that.state.model = $(that.wrapSelector('#model')).val(); } - that.insEditor.show(); + that.modelEditor.reload(); }); //================================================================ @@ -187,7 +188,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { $(tag).val(value); break; } @@ -215,7 +216,7 @@ define([ // render tag config.options.forEach(opt => { optBox.appendFormatLine('' - , opt.name, opt.name, opt.name); + , 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); }); @@ -229,13 +230,12 @@ define([ render() { super.render(); - // Instance Editor - this.insEditor = new InstanceEditor(this, "model", "instanceEditor"); - this.insEditor.show(); + // Model Editor + this.modelEditor = new ModelEditor(this, "model", "instanceEditor"); } generateCode() { - let { modelControlType, modelType, userOption, featureData, targetData, allocateTo } = this.state; + let { modelControlType, modelType, userOption, allocateToCreation, model } = this.state; let code = new com_String(); if (modelControlType == 'creation') { /** @@ -251,15 +251,14 @@ define([ // model code let modelCode = config.code; modelCode = com_generator.vp_codeGenerator(this, config, this.state, userOption); - code.appendFormat('{0} = {1}', allocateTo, modelCode); + code.appendFormat('{0} = {1}', allocateToCreation, modelCode); } else { /** * Model Selection * --- * ... */ - - + code.append(this.modelEditor.getCode({'${model}': model})); } return code.toString(); diff --git a/js/m_ml/dataSplit.js b/js/m_ml/dataSplit.js index bdf7bcd9..0361f213 100644 --- a/js/m_ml/dataSplit.js +++ b/js/m_ml/dataSplit.js @@ -135,7 +135,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { $(tag).val(value); break; } diff --git a/js/m_ml/evaluation.js b/js/m_ml/evaluation.js index 432e8f31..53d74a02 100644 --- a/js/m_ml/evaluation.js +++ b/js/m_ml/evaluation.js @@ -31,7 +31,7 @@ define([ this.config.dataview = false; this.state = { - modelType: 'clf', + modelType: 'rgs', predictData: 'pred', targetData: 'y_test', // classification @@ -97,7 +97,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { $(tag).val(value); break; } @@ -118,15 +118,16 @@ define([ } generateCode() { + let codeCells = []; let code = new com_String(); let { modelType, predictData, targetData, // classification - confusion_matrix, report, accuracy, precision, recall, f1_score, + confusion_matrix, report, accuracy, precision, recall, f1_score, roc_curve, auc, // regression coefficient, intercept, r_squared, mae, mape, rmse, scatter_plot, // clustering - sizeOfClusters, silhouetteScore + sizeOfClusters, silhouetteScore, ari, nm } = this.state; //==================================================================== @@ -134,28 +135,56 @@ define([ //==================================================================== if (modelType == 'clf') { if (confusion_matrix) { + code = new com_String(); code.appendLine("# Confusion Matrix"); - code.appendFormatLine('pd.crosstab({0}, {1}, margins=True)', targetData, predictData); + code.appendFormat('pd.crosstab({0}, {1}, margins=True)', targetData, predictData); + codeCells.push(code.toString()); } if (report) { + code = new com_String(); code.appendLine("# Classification report"); - code.appendFormatLine('print(metrics.classification_report({0}, {1}))', targetData, predictData); + code.appendFormat('print(metrics.classification_report({0}, {1}))', targetData, predictData); + codeCells.push(code.toString()); } if (accuracy) { + code = new com_String(); code.appendLine("# Accuracy"); - code.appendFormatLine('metrics.accuracy_score({0}, {1})', targetData, predictData); + code.appendFormat('metrics.accuracy_score({0}, {1})', targetData, predictData); + codeCells.push(code.toString()); } if (precision) { + code = new com_String(); code.appendLine("# Precision"); - code.appendFormatLine("metrics.precision_score({0}, {1}, average='weighted')", targetData, predictData); + code.appendFormat("metrics.precision_score({0}, {1}, average='weighted')", targetData, predictData); + codeCells.push(code.toString()); } if (recall) { + code = new com_String(); code.appendLine("# Recall"); - code.appendFormatLine("metrics.recall_score({0}, {1}, average='weighted')", targetData, predictData); + code.appendFormat("metrics.recall_score({0}, {1}, average='weighted')", targetData, predictData); + codeCells.push(code.toString()); } if (f1_score) { + code = new com_String(); code.appendLine("# F1-score"); - code.appendFormatLine("metrics.f1_score({0}, {1}, average='weighted')", targetData, predictData); + code.appendFormat("metrics.f1_score({0}, {1}, average='weighted')", targetData, predictData); + codeCells.push(code.toString()); + } + if (roc_curve) { + code = new com_String(); + code.appendLine("# ROC Curve"); + code.appendFormatLine("fpr, tpr, thresholds = roc_curve({0}, svc.decision_function({1}}))", predictData, targetData); + code.appendLine("plt.plot(fpr, tpr, label='ROC Curve')"); + code.appendLine("plt.xlabel('Sensitivity') "); + code.append("plt.ylabel('Specificity') ") + codeCells.push(code.toString()); + } + if (auc) { + code = new com_String(); + code.appendLine("# AUC"); + code.appendFormatLine("fpr, tpr, thresholds = roc_curve({0}, svc.decision_function({1}}))", predictData, targetData); + code.append("metrics.auc(fpr, tpr)"); + codeCells.push(code.toString()); } } @@ -163,56 +192,80 @@ define([ // Regression //==================================================================== if (modelType == 'rgs') { - if (coefficient) { - code.appendLine("# Coefficient (scikit-learn only)"); - code.appendFormatLine('model.coef_'); - } - if (intercept) { - code.appendLine("# Intercept (scikit-learn only)"); - code.appendFormatLine('model.intercept_'); - } + // if (coefficient) { + // code.appendLine("# Coefficient (scikit-learn only)"); + // code.appendFormatLine('model.coef_'); + // } + // if (intercept) { + // code.appendLine("# Intercept (scikit-learn only)"); + // code.appendFormatLine('model.intercept_'); + // } if (r_squared) { + code = new com_String(); code.appendLine("# R square"); - code.appendFormatLine('metrics.r2_score({0}, {1})', targetData, predictData); + code.appendFormat('metrics.r2_score({0}, {1})', targetData, predictData); + codeCells.push(code.toString()); } if (mae) { + code = new com_String(); code.appendLine("# MAE(Mean Absolute Error)"); - code.appendFormatLine('metrics.mean_absolute_error({0}, {1})', targetData, predictData); + code.appendFormat('metrics.mean_absolute_error({0}, {1})', targetData, predictData); + codeCells.push(code.toString()); } if (mape) { + code = new com_String(); code.appendLine("# MAPE(Mean Absolute Percentage Error)"); code.appendLine('def MAPE(y_test, y_pred):'); code.appendLine(' return np.mean(np.abs((y_test - pred) / y_test)) * 100'); code.appendLine(); - code.appendFormatLine('MAPE({0}, {1})', targetData, predictData); + code.appendFormat('MAPE({0}, {1})', targetData, predictData); + codeCells.push(code.toString()); } if (rmse) { + code = new com_String(); code.appendLine("# RMSE(Root Mean Squared Error)"); - code.appendFormatLine('metrics.mean_squared_error({0}, {1})**0.5', targetData, predictData); + code.appendFormat('metrics.mean_squared_error({0}, {1})**0.5', targetData, predictData); + codeCells.push(code.toString()); } if (scatter_plot) { + code = new com_String(); code.appendLine('# Regression plot'); code.appendFormatLine('plt.scatter({0}, {1})', targetData, predictData); code.appendFormatLine("plt.xlabel('{0}')", targetData); code.appendFormatLine("plt.ylabel('{1}')", predictData); - code.appendLine('plt.show()'); + code.append('plt.show()'); + codeCells.push(code.toString()); } } //==================================================================== // Clustering //==================================================================== if (modelType == 'cls') { - if (sizeOfClusters) { - code.appendLine("# Size of clusters"); - code.appendFormatLine("print(f'Size of clusters: {np.bincount({0})}')", predictData); - } + // if (sizeOfClusters) { + // code.appendLine("# Size of clusters"); + // code.appendFormatLine("print(f'Size of clusters: {np.bincount({0})}')", predictData); + // } if (silhouetteScore) { + code = new com_String(); code.appendLine("# Silhouette score"); - code.appendFormatLine("print(f'Silhouette score: {metrics.cluster.silhouette_score({0}, {1})}')", targetData, predictData); + code.appendFormat("print(f'Silhouette score: {metrics.cluster.silhouette_score({0}, {1})}')", targetData, predictData); + codeCells.push(code.toString()); + } + if (ari) { + code = new com_String(); + code.appendLine("# ARI"); + code.appendFormat("print(f'ARI: {metrics.cluster.adjusted_rand_score({0}, {1})}')", targetData, predictData); + codeCells.push(code.toString()); + } + if (nm) { + code = new com_String(); + code.appendLine("# NM"); + code.appendFormat("print(f'NM: {metrics.cluster.normalized_mutual_info_score({0}, {1})}')", targetData, predictData); + codeCells.push(code.toString()); } } - // FIXME: as seperated cells - return code.toString(); + // return as seperated cells + return codeCells; } } diff --git a/js/m_ml/fitting.js b/js/m_ml/fitting.js index 0440bb28..937cdc7b 100644 --- a/js/m_ml/fitting.js +++ b/js/m_ml/fitting.js @@ -95,7 +95,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { $(tag).val(value); break; } diff --git a/js/m_ml/modelSelection.js b/js/m_ml/modelSelection.js index fc1e8dfd..a0873b2b 100644 --- a/js/m_ml/modelSelection.js +++ b/js/m_ml/modelSelection.js @@ -135,7 +135,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { $(tag).val(value); break; } diff --git a/js/m_ml/prediction.js b/js/m_ml/prediction.js index a5fe1485..1d62ec03 100644 --- a/js/m_ml/prediction.js +++ b/js/m_ml/prediction.js @@ -87,7 +87,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { $(tag).val(value); break; } diff --git a/js/m_ml/transformation.js b/js/m_ml/transformation.js index b2fcaa9f..5f4b1801 100644 --- a/js/m_ml/transformation.js +++ b/js/m_ml/transformation.js @@ -87,7 +87,7 @@ define([ switch(tagName) { case 'INPUT': let inputType = $(tag).prop('type'); - if (inputType == 'text' || inputType == 'number') { + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { $(tag).val(value); break; } diff --git a/js/menu/MenuItem.js b/js/menu/MenuItem.js index f57643bc..2d3d3d7c 100644 --- a/js/menu/MenuItem.js +++ b/js/menu/MenuItem.js @@ -55,10 +55,7 @@ define([ switch(color) { case 0: return 'vp-color-preparing'; - case 1: - case 2: - case 3: - case 4: + default: return 'vp-color-apps' + color; } } else {