diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..1b6525f0 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: visualpython diff --git a/.github/ISSUE_TEMPLATE/content-contribution.md b/.github/ISSUE_TEMPLATE/content-contribution.md new file mode 100644 index 00000000..e8f3a92e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/content-contribution.md @@ -0,0 +1,16 @@ +--- +name: Content contribution +about: Share contents to encourage using visualpython (e.g. gitbook, Youtube, blog, + ...) +title: '' +labels: documentation +assignees: '' + +--- + +**Share created contents** +Write and share your contents to encourage using visualpython. +Use external links to share your contents. + +**Need help** +If you need help for creating contents, you can request other contributors to join. diff --git a/.github/ISSUE_TEMPLATE/design-fix.md b/.github/ISSUE_TEMPLATE/design-fix.md new file mode 100644 index 00000000..a3eb3813 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/design-fix.md @@ -0,0 +1,18 @@ +--- +name: Design fix +about: Suggest an idea for design and ui +title: '' +labels: design fix +assignees: '' + +--- + +**Is your suggestion related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the design/style you'd like** +A clear and concise description of what you want to happen. +Design images needed to clearly understand + +**Additional context** +Add any other context or screenshots about the design suggestion here. diff --git a/data/libraries.json b/data/libraries.json index 5cd63821..bb205425 100644 --- a/data/libraries.json +++ b/data/libraries.json @@ -3328,6 +3328,60 @@ } } ] + }, + { + "id" : "pkg_stat", + "type" : "package", + "level": 0, + "name" : "Statistics", + "path" : "visualpython - statistics", + "desc" : "Statistics modules", + "open" : true, + "grid" : true, + "item" : [ + { + "id" : "stat_descriptive", + "type" : "function", + "level": 1, + "name" : "Descriptive Stat", + "tag" : "DESCRIPTIVE,STATISTICS,STAT", + "path" : "visualpython - statistics - descriptive", + "desc" : "Descriptive Stat", + "file" : "m_stat/DescriptiveStat", + "apps" : { + "color": 6, + "icon": "apps/apps_dataset.svg" + } + }, + { + "id" : "stat_analysis", + "type" : "function", + "level": 1, + "name" : "Stat Analysis", + "tag" : "ANALYSIS,STATISTICS,STAT", + "path" : "visualpython - statistics - analysis", + "desc" : "Analysis", + "file" : "m_stat/Analysis", + "apps" : { + "color": 6, + "icon": "apps/apps_datasplit.svg" + } + }, + { + "id" : "stat_test", + "type" : "function", + "level": 1, + "name" : "Test", + "tag" : "TEST,STATISTICS,STAT", + "path" : "visualpython - statistics - test", + "desc" : "Test", + "file" : "m_stat/Test", + "apps" : { + "color": 6, + "icon": "apps/apps_dataprep.svg" + } + } + ] } ] } diff --git a/data/m_stat/statLibrary.js b/data/m_stat/statLibrary.js new file mode 100644 index 00000000..054af1b8 --- /dev/null +++ b/data/m_stat/statLibrary.js @@ -0,0 +1,656 @@ +define([ +], function () { + /** + * name + * library + * description + * code + * options: [ + * { + * name + * label + * [optional] + * component : + * - 1darr / 2darr / ndarr / scalar / param / dtype / tabblock + * default + * required + * usePair + * code + * } + * ] + */ + 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(${sparse}${handle_unknown}${etc})', + options: [ + { name: 'sparse', component: ['bool_select'], default: 'False', usePair: true }, + { name: 'handle_unknown', component: ['option_suggest'], usePair: true, + options: ['error', 'ignore'], default: 'error' }, + ] + }, + 'prep-label': { + name: 'LabelEncoder', + import: 'from sklearn.preprocessing import LabelEncoder', + code: 'LabelEncoder()', + options: [ + + ] + }, + 'prep-ordinal': { + name: 'OrdinalEncoder', + import: 'from sklearn.preprocessing import 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(${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 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(${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(${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(${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(${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${etc})', + options: [ + + ] + }, + 'prep-func-trsfrm-exp': { + name: 'Exponential Scaling', + import: 'from sklearn.preprocessing import FunctionTransformer', + code: 'FunctionTransformer(np.expm1${etc})', + options: [ + + ] + }, + 'prep-poly-feat': { + name: 'Polynomial Features', + import: 'from sklearn.preprocessing import PolynomialFeatures', + code: 'PolynomialFeatures(${etc})', + options: [ + + ] + }, + 'prep-kbins-discretizer': { + name: 'KBins Discretizer', + import: 'from sklearn.preprocessing import KBinsDiscretizer', + code: 'KBinsDiscretizer(${n_bins}${strategy}${encode}${etc})', + options: [ + { name: 'n_bins', component: ['input_number'], default: 5, usePair: true }, + { name: 'strategy', component: ['option_select'], type: 'text', default: 'quantile', usePair: true, + options: ['uniform', 'quantiile', 'kmeans'] }, + { name: 'encode', component: ['option_select'], type: 'text', default: 'onehot', usePair: true, + options: ['onehot', 'onehot-dense', 'ordinal'] } + ] + }, + 'make-column-transformer': { + name: 'MakeColumnTransformer', + import: 'from sklearn.compose import make_column_transformer', + code: 'make_column_transformer(${mct_code})', + options: [ + + ] + }, + /** Regression */ + 'ln-rgs': { + name: 'LinearRegression', + import: 'from sklearn.linear_model import LinearRegression', + 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(${alpha}${etc})', + options: [ + { name: 'alpha', component: ['input_number'], default: 1.0, usePair: true } + ] + }, + 'lasso': { + name: 'Lasso', + import: 'from sklearn.linear_model import Lasso', + code: 'Lasso(${alpha}${etc})', + options: [ + { name: 'alpha', component: ['input_number'], default: 1.0, usePair: true } + ] + }, + 'elasticnet': { + name: 'ElasticNet', + import: 'from sklearn.linear_model import ElasticNet', + code: 'ElasticNet(${alpha}${l1_ratio}${etc})', + options: [ + { name: 'alpha', component: ['input_number'], default: 1.0, usePair: true }, + { name: 'l1_ratio', component: ['input_number'], default: 0.5, usePair: true } + ] + }, + 'sv-rgs': { + name: 'SVR', + import: 'from sklearn.svm import SVR', + code: 'SVR(${C}${kernel}${degree}${gamma}${coef0}${random_state}${etc})', + options: [ + { name: 'C', component: ['input_number'], placeholder: '1.0', usePair: true, step: 0.1, min: 0 }, + { name: 'kernel', component: ['option_select'], type: 'text', usePair: true, + options: ['linear', 'poly', 'rbf', 'sigmoid', 'precomputed'], default: 'rbf' }, + { name: 'degree', component: ['input_number'], placeholder: '3', usePair: true }, + { name: 'gamma', component: ['option_suggest'], usePair: true, + options: ["'scale'", "'auto'"], default: "'scale'" }, + { name: 'coef0', component: ['input_number'], placeholder: '0.0', usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + 'dt-rgs': { + name: 'DecisionTreeRegressor', + import: 'from sklearn.tree import DecisionTreeRegressor', + code: 'DecisionTreeRegressor(${criterion}${max_depth}${min_samples_split}${random_state}${etc})', + options: [ + { 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 }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + 'rf-rgs': { + name: 'RandomForestRegressor', + import: 'from sklearn.ensemble import RandomForestRegressor', + 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'], 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 }, + { name: 'n_jobs', component: ['input_number'], placeholder: 'None', usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + 'gbm-rgs': { + name: 'GradientBoostingRegressor', + import: 'from sklearn.ensemble import GradientBoostingRegressor', + code: 'GradientBoostingRegressor(${loss}${learning_rate}${n_estimators}${criterion}${random_state}${etc})', + options: [ + { 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'], 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 } + ] + }, + 'xgb-rgs': { + name: 'XGBRegressor', + install: '!pip install xgboost', + import: 'from xgboost import XGBRegressor', + code: 'XGBRegressor(${n_estimators}${max_depth}${learning_rate}${gamma}${random_state}${etc})', + options: [ + { name: 'n_estimators', component: ['input_number'], default: 100, usePair: true }, + { name: 'max_depth', component: ['input_number'], placeholder: 'None', usePair: true }, + { name: 'learning_rate', component: ['input_number'], placeholder: 0.1, usePair: true }, + { name: 'gamma', component: ['input_number'], placeholder: 0.1, usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + 'lgbm-rgs': { + name: 'LGBMRegressor', + install: '!pip install lightgbm', + 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'], 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 }, + { name: 'n_estimators', component: ['input_number'], default: 100, usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + 'cb-rgs': { + name: 'CatBoostRegressor', + install: '!pip install catboost', + import: 'from catboost import CatBoostRegressor', + 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'], type: 'text', default: 'RMSE', type:'text', usePair: true, + options: ['RMSE', 'absolute_error', 'huber', 'quantile'] }, + { 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 }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + /** Classification */ + 'lg-rgs': { + name: 'LogisticRegression', + import: 'from sklearn.linear_model import LogisticRegression', + code: 'LogisticRegression(${penalty}${C}${random_state}${etc})', + options: [ + { 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, step: 0.1, min: 0 }, + { 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: 'SVC', + import: 'from sklearn.svm import SVC', + code: 'SVC(${C}${kernel}${degree}${gamma}${coef0}${random_state}${etc})', + options: [ + { name: 'C', component: ['input_number'], placeholder: '1.0', usePair: true, step: 0.1, min: 0 }, + { name: 'kernel', component: ['option_select'], type: 'text', usePair: true, + options: ['linear', 'poly', 'rbf', 'sigmoid', 'precomputed'], default: 'rbf' }, + { name: 'degree', component: ['input_number'], placeholder: '3', usePair: true }, + { name: 'gamma', component: ['option_suggest'], usePair: true, + options: ["'scale'", "'auto'"], default: "'scale'" }, + { name: 'coef0', component: ['input_number'], placeholder: '0.0', usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + 'dt-clf': { + name: 'DecisionTreeClassifier', + import: 'from sklearn.tree import DecisionTreeClassifier', + code: 'DecisionTreeClassifier(${criterion}${max_depth}${min_samples_split}${random_state}${etc})', + options: [ + { 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 }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + 'rf-clf': { + name: 'RandomForestClassifier', + import: 'from sklearn.ensemble import RandomForestClassifier', + 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'], 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 }, + { name: 'n_jobs', component: ['input_number'], placeholder: 'None', usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + 'gbm-clf': { + name: 'GradientBoostingClassifier', + import: 'from sklearn.ensemble import GradientBoostingClassifier', + code: 'GradientBoostingClassifier(${loss}${learning_rate}${n_estimators}${criterion}${random_state}${etc})', + options: [ + { 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'], 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 } + ] + }, + 'xgb-clf': { + name: 'XGBClassifier', + install: '!pip install xgboost', + import: 'from xgboost import XGBClassifier', + code: 'XGBClassifier(${n_estimators}${max_depth}${learning_rate}${gamma}${random_state}${etc})', + options: [ + { name: 'n_estimators', component: ['input_number'], default: 100, usePair: true }, + { name: 'max_depth', component: ['input_number'], placeholder: 'None', usePair: true }, + { name: 'learning_rate', component: ['input_number'], placeholder: 0.1, usePair: true }, + { name: 'gamma', component: ['input_number'], placeholder: 0.1, usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + 'lgbm-clf': { + name: 'LGBMClassifier', + install: '!pip install lightgbm', + 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'], 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 }, + { name: 'n_estimators', component: ['input_number'], default: 100, usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + 'cb-clf': { + name: 'CatBoostClassifier', + install: '!pip install catboost', + import: 'from catboost import CatBoostClassifier', + 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'], type: 'text', default: 'RMSE', type:'text', usePair: true, + options: ['RMSE', 'absolute_error', 'huber', 'quantile'] }, + { 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 }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + /** 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: [ + { name: 'generation', component: ['input_number'], default: 100, usePair: true }, + { name: 'population_size', component: ['input_number'], default: 100, usePair: true }, + { name: 'cv', component: ['input_number'], default: 5, usePair: true }, + { 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: [ + { name: 'generation', component: ['input_number'], default: 100, usePair: true }, + { name: 'population_size', component: ['input_number'], default: 100, usePair: true }, + { name: 'cv', component: ['input_number'], default: 5, usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + /** Clustering */ + 'k-means': { + name: 'KMeans', + import: 'from sklearn.cluster import KMeans', + code: 'KMeans(${n_clusters}${random_state}${etc})', + options: [ + { name: 'n_clusters', component: ['input_number'], default: 8, usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + 'agg-cls': { + name: 'AgglomerativeClustering', + import: 'from sklearn.cluster import AgglomerativeClustering', + code: 'AgglomerativeClustering(${n_clusters}${random_state}${etc})', + options: [ + { name: 'n_clusters', component: ['input_number'], default: 2, usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + 'gaus-mix': { + name: 'GaussianMixture', + import: 'from sklearn.mixture import GaussianMixture', + code: 'GaussianMixture(${n_components}${random_state}${etc})', + options: [ + { name: 'n_components', component: ['input_number'], default: 1, usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + 'dbscan': { + name: 'DBSCAN', + import: 'from sklearn.cluster import DBSCAN', + code: 'DBSCAN(${eps}${min_samples}${etc})', + options: [ + { name: 'eps', component: ['input_number'], default: 0.5, usePair: true }, + { name: 'min_samples', component: ['input_number'], default: 5, usePair: true } + ] + }, + /** Dimension Reduction */ + 'pca': { + name: 'PCA(Principal Component Analysis)', + import: 'from sklearn.decomposition import PCA', + code: 'PCA(${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 } + ] + }, + 'lda': { + name: 'LDA(Linear Discriminant Analysis)', + import: 'from sklearn.discriminant_analysis import LinearDiscriminantAnalysis', + code: 'LinearDiscriminantAnalysis(${n_components}${etc})', + options: [ + { name: 'n_components', component: ['input_number'], placeholder: 'None', usePair: true } + ] + }, + 'svd': { + name: 'Truncated SVD', + import: 'from sklearn.decomposition import TruncatedSVD', + code: 'TruncatedSVD(${n_components}${random_state}${etc})', + options: [ + { name: 'n_components', component: ['input_number'], default: 2, usePair: true }, + { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } + ] + }, + 'nmf': { + 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 } + ] + } + } + + return ML_LIBRARIES; +}); \ No newline at end of file diff --git a/html/m_stat/Analysis.html b/html/m_stat/Analysis.html new file mode 100644 index 00000000..739aa2e0 --- /dev/null +++ b/html/m_stat/Analysis.html @@ -0,0 +1,27 @@ + +
+
+ +
+
+
+
+ +
+ + +
+
+
+ +
+
+
+ + +
+
+
+ \ No newline at end of file diff --git a/html/m_stat/Test.html b/html/m_stat/Test.html new file mode 100644 index 00000000..739aa2e0 --- /dev/null +++ b/html/m_stat/Test.html @@ -0,0 +1,27 @@ + +
+
+ +
+
+
+
+ +
+ + +
+
+
+ +
+
+
+ + +
+
+
+ \ No newline at end of file diff --git a/js/m_stat/Analysis.js b/js/m_stat/Analysis.js new file mode 100644 index 00000000..36c8154c --- /dev/null +++ b/js/m_stat/Analysis.js @@ -0,0 +1,329 @@ +/* + * Project Name : Visual Python + * Description : GUI-based Python code generator + * File Name : Classification.js + * Author : Black Logic + * Note : Model selection and fitting + * License : GNU GPLv3 with Visual Python special exception + * Date : 2022. 02. 07 + * Change Date : + */ + +//============================================================================ +// [CLASS] Classification +//============================================================================ +define([ + 'text!vp_base/html/m_ml/model.html!strip', + 'vp_base/js/com/com_util', + 'vp_base/js/com/com_interface', + 'vp_base/js/com/com_String', + 'vp_base/js/com/com_generatorV2', + 'vp_base/data/m_ml/mlLibrary', + 'vp_base/js/com/component/PopupComponent', + 'vp_base/js/com/component/VarSelector2', + 'vp_base/js/com/component/ModelEditor' +], function(msHtml, com_util, com_interface, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, ModelEditor) { + + /** + * Classification + */ + class Classification extends PopupComponent { + _init() { + super._init(); + this.config.sizeLevel = 2; + this.config.dataview = false; + + this.state = { + // model creation + modelControlType: 'creation', + modelType: 'lg-rgs', + userOption: '', + featureData: 'X_train', + targetData: 'y_train', + allocateToCreation: 'model', + // model selection + model: '', + method: '', + ...this.state + } + + this.modelConfig = ML_LIBRARIES; + + this.modelTypeList = { + 'Classfication': ['lg-rgs', 'bern-nb', 'mulnom-nb', 'gaus-nb', 'sv-clf', 'dt-clf', 'rf-clf', 'gbm-clf', 'xgb-clf', 'lgbm-clf', 'cb-clf'], + } + + + } + + _bindEvent() { + super._bindEvent(); + /** Implement binding events */ + var that = this; + // select model control type + $(this.wrapSelector('#modelControlType')).on('change', function() { + let modelControlType = $(this).val(); + // show/hide model box + $(that.wrapSelector('.vp-model-box')).hide(); + $(that.wrapSelector(`.vp-model-box[data-type="${modelControlType}"]`)).show(); + }); + + // select model type + $(this.wrapSelector('#modelType')).on('change', function() { + let modelType = $(this).val(); + that.state.modelType = modelType; + $(that.wrapSelector('.vp-model-option-box')).html(that.templateForOption(modelType)); + that.viewOption(); + + // show install button + if (that.modelConfig[modelType].install != undefined) { + $(that.wrapSelector('#vp_installLibrary')).show(); + } else { + $(that.wrapSelector('#vp_installLibrary')).hide(); + } + }); + + // install library + $(this.wrapSelector('#vp_installLibrary')).on('click', function() { + let config = that.modelConfig[that.state.modelType]; + if (config && config.install != undefined) { + // insert install code + com_interface.insertCell('code', config.install, true, 'Machine Learning > Classification'); + } + }); + + // change model + $(this.wrapSelector('#model')).on('change', function() { + that.modelEditor.reload(); + }); + } + + templateForBody() { + let page = $(msHtml); + + let that = this; + + // model control type + $(page).find('.vp-model-box').hide(); + $(page).find(`.vp-model-box[data-type="${this.state.modelControlType}"]`).show(); + + //================================================================ + // Model creation + //================================================================ + // model types + let modelTypeTag = new com_String(); + Object.keys(this.modelTypeList).forEach(modelCategory => { + let modelOptionTag = new com_String(); + that.modelTypeList[modelCategory].forEach(opt => { + let optConfig = that.modelConfig[opt]; + let selectedFlag = ''; + if (opt == that.state.modelType) { + selectedFlag = 'selected'; + } + modelOptionTag.appendFormatLine('', + opt, selectedFlag, optConfig.name); + }) + modelTypeTag.appendFormatLine('{1}', + modelCategory, modelOptionTag.toString()); + }); + $(page).find('#modelType').html(modelTypeTag.toString()); + + // show install button + if (this.modelConfig[this.state.modelType].install != undefined) { + $(page).find('#vp_installLibrary').show(); + } else { + $(page).find('#vp_installLibrary').hide(); + } + + // render option page + $(page).find('.vp-model-option-box').html(this.templateForOption(this.state.modelType)); + + let varSelector = new VarSelector2(this.wrapSelector()); + varSelector.setComponentID('featureData'); + varSelector.addClass('vp-state vp-input'); + varSelector.setValue(this.state.featureData); + $(page).find('#featureData').replaceWith(varSelector.toTagString()); + + varSelector = new VarSelector2(this.wrapSelector()); + varSelector.setComponentID('targetData'); + varSelector.addClass('vp-state vp-input'); + varSelector.setValue(this.state.targetData); + $(page).find('#targetData').replaceWith(varSelector.toTagString()); + + //================================================================ + // Model selection + //================================================================ + // set model list + let modelOptionTag = new com_String(); + vpKernel.getModelList('Classification').then(function(resultObj) { + let { result } = resultObj; + var modelList = JSON.parse(result); + modelList && modelList.forEach(model => { + let selectFlag = ''; + if (model.varName == that.state.model) { + selectFlag = 'selected'; + } + modelOptionTag.appendFormatLine('', + model.varName, model.varType, selectFlag, model.varName, model.varType); + }); + $(page).find('#model').html(modelOptionTag.toString()); + $(that.wrapSelector('#model')).html(modelOptionTag.toString()); + + if (!that.state.model || that.state.model == '') { + that.state.model = $(that.wrapSelector('#model')).val(); + } + + that.modelEditor.show(); + }); + + //================================================================ + // Load state + //================================================================ + Object.keys(this.state).forEach(key => { + let tag = $(page).find('#' + key); + let tagName = $(tag).prop('tagName'); // returns with UpperCase + let value = that.state[key]; + if (value == undefined) { + return; + } + switch(tagName) { + case 'INPUT': + let inputType = $(tag).prop('type'); + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { + $(tag).val(value); + break; + } + if (inputType == 'checkbox') { + $(tag).prop('checked', value); + break; + } + break; + case 'TEXTAREA': + case 'SELECT': + default: + $(tag).val(value); + break; + } + }); + + return page; + } + + templateForOption(modelType) { + let config = this.modelConfig[modelType]; + let state = this.state; + + let optBox = new com_String(); + // render tag + config.options.forEach(opt => { + optBox.appendFormatLine('' + , opt.name, opt.name, com_util.optionToLabel(opt.name)); + let content = com_generator.renderContent(this, opt.component[0], opt, state); + optBox.appendLine(content[0].outerHTML); + }); + // render user option + optBox.appendFormatLine('', 'userOption', 'User option'); + optBox.appendFormatLine('', + 'userOption', 'key=value, ...', this.state.userOption); + return optBox.toString(); + } + + viewOption() { + // SVC - kernel selection + if (this.state.modelType == 'sv-clf') { + let kernelType = this.state.kernel; + switch (kernelType) { + case undefined: // default = rbf + case '': + case 'rbf': // gamma + $(this.wrapSelector('label[for="gamma"]')).show(); + $(this.wrapSelector('#gamma')).show(); + // hide others + $(this.wrapSelector('label[for="degree"]')).hide(); + $(this.wrapSelector('#degree')).hide(); + $(this.wrapSelector('label[for="coef0"]')).hide(); + $(this.wrapSelector('#coef0')).hide(); + break; + case 'poly': // gamma / degree / coef0 + $(this.wrapSelector('label[for="gamma"]')).show(); + $(this.wrapSelector('#gamma')).show(); + $(this.wrapSelector('label[for="degree"]')).show(); + $(this.wrapSelector('#degree')).show(); + $(this.wrapSelector('label[for="coef0"]')).show(); + $(this.wrapSelector('#coef0')).show(); + break; + case 'sigmoid': // gamma / coef0 + $(this.wrapSelector('label[for="gamma"]')).show(); + $(this.wrapSelector('#gamma')).show(); + $(this.wrapSelector('label[for="coef0"]')).show(); + $(this.wrapSelector('#coef0')).show(); + // hide others + $(this.wrapSelector('label[for="degree"]')).hide(); + $(this.wrapSelector('#degree')).hide(); + break; + default: + // hide others + $(this.wrapSelector('label[for="gamma"]')).hide(); + $(this.wrapSelector('#gamma')).hide(); + $(this.wrapSelector('label[for="degree"]')).hide(); + $(this.wrapSelector('#degree')).hide(); + $(this.wrapSelector('label[for="coef0"]')).hide(); + $(this.wrapSelector('#coef0')).hide(); + break; + } + + // Model Creation - SVC kernel selection + let that = this; + $(this.wrapSelector('#kernel')).off('change'); + $(this.wrapSelector('#kernel')).change(function() { + that.state.kernel = $(this).val(); + that.viewOption(); + }); + } + + } + + render() { + super.render(); + + // Model Creation - dynamically view options + this.viewOption(); + + // Model Editor + this.modelEditor = new ModelEditor(this, "model", "instanceEditor"); + } + + generateCode() { + let { modelControlType, modelType, userOption, allocateToCreation, model } = this.state; + let code = new com_String(); + if (modelControlType == 'creation') { + /** + * Model Creation + * --- + * from module import model_function + * model = Model(key=value, ...) + */ + let config = this.modelConfig[modelType]; + code.appendLine(config.import); + code.appendLine(); + + // model code + let modelCode = config.code; + modelCode = com_generator.vp_codeGenerator(this, config, this.state, (userOption != ''? ', ' + userOption : '')); + code.appendFormat('{0} = {1}', allocateToCreation, modelCode); + } else { + /** + * Model Selection + * --- + * ... + */ + code.append(this.modelEditor.getCode({'${model}': model})); + } + + return code.toString(); + } + + } + + return Classification; +}); \ No newline at end of file diff --git a/js/m_stat/Test.js b/js/m_stat/Test.js new file mode 100644 index 00000000..2d3e5154 --- /dev/null +++ b/js/m_stat/Test.js @@ -0,0 +1,331 @@ +/* + * Project Name : Visual Python + * Description : GUI-based Python code generator + * File Name : Classification.js + * Author : Black Logic + * Note : Model selection and fitting + * License : GNU GPLv3 with Visual Python special exception + * Date : 2022. 02. 07 + * Change Date : + */ + +//============================================================================ +// [CLASS] Classification +//============================================================================ +define([ + 'text!vp_base/html/m_ml/model.html!strip', // TODO : 본 모듈의 화면을 구성할 html 파일명을 찾아 연결 + 'vp_base/js/com/com_util', + 'vp_base/js/com/com_interface', + 'vp_base/js/com/com_String', + 'vp_base/js/com/com_generatorV2', + 'vp_base/data/m_ml/mlLibrary', // TODO : 통계 모듈 메소드에 대한 공통정보는 library에 정리 + 'vp_base/js/com/component/PopupComponent', + 'vp_base/js/com/component/VarSelector2', + 'vp_base/js/com/component/ModelEditor' +], function(msHtml, com_util, com_interface, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, ModelEditor) { + + /** + * Classification + */ + class Classification extends PopupComponent { + _init() { + super._init(); + this.config.sizeLevel = 2; + this.config.dataview = false; + + this.state = { // TODO : 화면 로딩과 동시에 세팅되어야 할 초기값 설정 + // model creation + modelControlType: 'creation', + modelType: 'lg-rgs', + userOption: '', + featureData: 'X_train', + targetData: 'y_train', + allocateToCreation: 'model', + // model selection + model: '', + method: '', + ...this.state + } + + this.modelConfig = ML_LIBRARIES; // TODO : ML_LIBRARY에 정리한 통계 메소드 정보 불러옴 + + this.modelTypeList = { // TODO : 통계 메소드 이름 정리 + 'Classfication': ['lg-rgs', 'bern-nb', 'mulnom-nb', 'gaus-nb', 'sv-clf', 'dt-clf', 'rf-clf', 'gbm-clf', 'xgb-clf', 'lgbm-clf', 'cb-clf'], + } + + + } + + _bindEvent() { + super._bindEvent(); + /** Implement binding events */ + var that = this; + + + // select model control type // TODO : 화면에서 리스트 박스의 선택에 따라 특정 변수 항목을 보이기/숨기기 등 처리 + $(this.wrapSelector('#modelControlType')).on('change', function() { + let modelControlType = $(this).val(); + // show/hide model box + $(that.wrapSelector('.vp-model-box')).hide(); // TODO : HTML에서 div class가 'vp-model-box'인 항목을 숨기기 + $(that.wrapSelector(`.vp-model-box[data-type="${modelControlType}"]`)).show(); + }); + + // select model type + $(this.wrapSelector('#modelType')).on('change', function() { + let modelType = $(this).val(); // TODO : 리스트박스에서 선택한 값을 변수로 넣음 + that.state.modelType = modelType; // TODO : 화면에서 계속 보관해야 할 변수는 that.state.변수명 에 저장 -> 36 line 참고 + $(that.wrapSelector('.vp-model-option-box')).html(that.templateForOption(modelType)); // TODO : 화면에서 그려줄 다양한 모델 옵션정보 HTML을 'templateForOption' 함수에서 생성한 뒤 HTML의 'vp-model-option-box'에 표시해 줌(test.html 17라인 참고) + that.viewOption(); + + // show install button // TODO : 모델에 따라 패키지 install 버튼을 보이기/숨기기 + if (that.modelConfig[modelType].install != undefined) { + $(that.wrapSelector('#vp_installLibrary')).show(); + } else { + $(that.wrapSelector('#vp_installLibrary')).hide(); + } + }); + + // install library // TODO : install 버튼을 클릭했을 때 수행할 동작을 지정 + $(this.wrapSelector('#vp_installLibrary')).on('click', function() { + let config = that.modelConfig[that.state.modelType]; // TODO : install 동작은 modelConfig -> ML_LIBRARY에 지정되어 있음 + if (config && config.install != undefined) { + // insert install code + com_interface.insertCell('code', config.install, true, 'Machine Learning > Classification'); // TODO : 화면에서의 팝업을 없애지 않고도 jupyter에 명령줄을 삽입해 줌 + } + }); + + // change model + $(this.wrapSelector('#model')).on('change', function() { + that.modelEditor.reload(); + }); + } + + templateForBody() { // TODO : html 스크립트를 html 파일에 정적으로 구성하지 않고, 자바스크립트에서 동적으로 생성하여 html에 표시해 주는 역할. + let page = $(msHtml); + + let that = this; + + // model control type + $(page).find('.vp-model-box').hide(); // TODO : HTML에서 vp-model-box class 를 찾아서 숨김 + $(page).find(`.vp-model-box[data-type="${this.state.modelControlType}"]`).show(); + + //================================================================ + // Model creation + //================================================================ + // model types + let modelTypeTag = new com_String(); + Object.keys(this.modelTypeList).forEach(modelCategory => { // TODO 모델 리스트('lg-rgs', 'bern-nb', 'mulnom-nb'...) 별로 for문을 돔 + let modelOptionTag = new com_String(); + that.modelTypeList[modelCategory].forEach(opt => { + let optConfig = that.modelConfig[opt]; + let selectedFlag = ''; + if (opt == that.state.modelType) { + selectedFlag = 'selected'; + } + modelOptionTag.appendFormatLine('', + opt, selectedFlag, optConfig.name); + }) + modelTypeTag.appendFormatLine('{1}', + modelCategory, modelOptionTag.toString()); + }); + $(page).find('#modelType').html(modelTypeTag.toString()); + + // show install button + if (this.modelConfig[this.state.modelType].install != undefined) { + $(page).find('#vp_installLibrary').show(); + } else { + $(page).find('#vp_installLibrary').hide(); + } + + // render option page + $(page).find('.vp-model-option-box').html(this.templateForOption(this.state.modelType)); // TODO : 옵션 부분은 별도의 함수(templateForOption)를 호출하여 작성 + + let varSelector = new VarSelector2(this.wrapSelector()); + varSelector.setComponentID('featureData'); + varSelector.addClass('vp-state vp-input'); + varSelector.setValue(this.state.featureData); + $(page).find('#featureData').replaceWith(varSelector.toTagString()); + + varSelector = new VarSelector2(this.wrapSelector()); + varSelector.setComponentID('targetData'); + varSelector.addClass('vp-state vp-input'); + varSelector.setValue(this.state.targetData); + $(page).find('#targetData').replaceWith(varSelector.toTagString()); + + //================================================================ + // Model selection + //================================================================ + // set model list + let modelOptionTag = new com_String(); + vpKernel.getModelList('Classification').then(function(resultObj) { + let { result } = resultObj; + var modelList = JSON.parse(result); + modelList && modelList.forEach(model => { + let selectFlag = ''; + if (model.varName == that.state.model) { + selectFlag = 'selected'; + } + modelOptionTag.appendFormatLine('', + model.varName, model.varType, selectFlag, model.varName, model.varType); + }); + $(page).find('#model').html(modelOptionTag.toString()); + $(that.wrapSelector('#model')).html(modelOptionTag.toString()); + + if (!that.state.model || that.state.model == '') { + that.state.model = $(that.wrapSelector('#model')).val(); + } + + that.modelEditor.show(); + }); + + //================================================================ + // Load state + //================================================================ + Object.keys(this.state).forEach(key => { + let tag = $(page).find('#' + key); + let tagName = $(tag).prop('tagName'); // returns with UpperCase + let value = that.state[key]; + if (value == undefined) { + return; + } + switch(tagName) { + case 'INPUT': + let inputType = $(tag).prop('type'); + if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') { + $(tag).val(value); + break; + } + if (inputType == 'checkbox') { + $(tag).prop('checked', value); + break; + } + break; + case 'TEXTAREA': + case 'SELECT': + default: + $(tag).val(value); + break; + } + }); + + return page; + } + + templateForOption(modelType) { // TODO : 각 모델의 옵션에 대한 화면을 별도의 함수로 구현 + let config = this.modelConfig[modelType]; + let state = this.state; + + let optBox = new com_String(); + // render tag + config.options.forEach(opt => { + optBox.appendFormatLine('' + , opt.name, opt.name, com_util.optionToLabel(opt.name)); + let content = com_generator.renderContent(this, opt.component[0], opt, state); + optBox.appendLine(content[0].outerHTML); + }); + // render user option + optBox.appendFormatLine('', 'userOption', 'User option'); + optBox.appendFormatLine('', + 'userOption', 'key=value, ...', this.state.userOption); + return optBox.toString(); + } + + viewOption() { // TODO : 모델에 따라 if문으로 분기하여 모델의 각 옵션 항목을 보이기/숨기기를 결정 + // SVC - kernel selection + if (this.state.modelType == 'sv-clf') { + let kernelType = this.state.kernel; + switch (kernelType) { + case undefined: // default = rbf + case '': + case 'rbf': // gamma + $(this.wrapSelector('label[for="gamma"]')).show(); + $(this.wrapSelector('#gamma')).show(); + // hide others + $(this.wrapSelector('label[for="degree"]')).hide(); + $(this.wrapSelector('#degree')).hide(); + $(this.wrapSelector('label[for="coef0"]')).hide(); + $(this.wrapSelector('#coef0')).hide(); + break; + case 'poly': // gamma / degree / coef0 + $(this.wrapSelector('label[for="gamma"]')).show(); + $(this.wrapSelector('#gamma')).show(); + $(this.wrapSelector('label[for="degree"]')).show(); + $(this.wrapSelector('#degree')).show(); + $(this.wrapSelector('label[for="coef0"]')).show(); + $(this.wrapSelector('#coef0')).show(); + break; + case 'sigmoid': // gamma / coef0 + $(this.wrapSelector('label[for="gamma"]')).show(); + $(this.wrapSelector('#gamma')).show(); + $(this.wrapSelector('label[for="coef0"]')).show(); + $(this.wrapSelector('#coef0')).show(); + // hide others + $(this.wrapSelector('label[for="degree"]')).hide(); + $(this.wrapSelector('#degree')).hide(); + break; + default: + // hide others + $(this.wrapSelector('label[for="gamma"]')).hide(); + $(this.wrapSelector('#gamma')).hide(); + $(this.wrapSelector('label[for="degree"]')).hide(); + $(this.wrapSelector('#degree')).hide(); + $(this.wrapSelector('label[for="coef0"]')).hide(); + $(this.wrapSelector('#coef0')).hide(); + break; + } + + // Model Creation - SVC kernel selection + let that = this; + $(this.wrapSelector('#kernel')).off('change'); + $(this.wrapSelector('#kernel')).change(function() { + that.state.kernel = $(this).val(); + that.viewOption(); + }); + } + + } + + render() { + super.render(); + + // Model Creation - dynamically view options + this.viewOption(); // TODO : 사용자가 선택한 모델에 따라 옵션을 동적으로 변경하면서 보여줘야 해서, 별도의 옵션 rendor용 함수를 추가로 호출 + + // Model Editor + this.modelEditor = new ModelEditor(this, "model", "instanceEditor"); // TODO 추후 모델의 학습에 연동되는 데이터 처리를 위한 것으로 짐작됨 -> 통계에서는 없어도 되어 보임 + } + + generateCode() { // TODO : 실제 파이썬 코드를 생성하는 부분 + let { modelControlType, modelType, userOption, allocateToCreation, model } = this.state; + let code = new com_String(); + if (modelControlType == 'creation') { // TODO : 모델 컨트롤 타입에 따라 코드 생성 스타일이 달라져서 본재하는 분기. 통계에서는 불필요해 보임. if문 없이 처리 가능할 것으로 생각됨 + /** + * Model Creation + * --- + * from module import model_function + * model = Model(key=value, ...) + */ + let config = this.modelConfig[modelType]; // TODO : 파이썬 구문은 ML_LIBRARY에 세팅된 것을 불러와서 처리 + code.appendLine(config.import); + code.appendLine(); + + // model code + let modelCode = config.code; + modelCode = com_generator.vp_codeGenerator(this, config, this.state, (userOption != ''? ', ' + userOption : '')); + code.appendFormat('{0} = {1}', allocateToCreation, modelCode); + } else { + /** + * Model Selection + * --- + * ... + */ + code.append(this.modelEditor.getCode({'${model}': model})); + } + + return code.toString(); + } + + } + + return Classification; +}); \ No newline at end of file