Github user edespino commented on a diff in the pull request:

    https://github.com/apache/incubator-madlib/pull/149#discussion_r127095011
  
    --- Diff: src/ports/postgres/modules/convex/mlp_igd.py_in ---
    @@ -0,0 +1,754 @@
    +# coding=utf-8
    +#
    +# Licensed to the Apache Software Foundation (ASF) under one
    +# or more contributor license agreements.  See the NOTICE file
    +# distributed with this work for additional information
    +# regarding copyright ownership.  The ASF licenses this file
    +# to you under the Apache License, Version 2.0 (the
    +# "License"); you may not use this file except in compliance
    +# with the License.  You may obtain a copy of the License at
    +#
    +#   http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing,
    +# software distributed under the License is distributed on an
    +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    +# KIND, either express or implied.  See the License for the
    +# specific language governing permissions and limitations
    +# under the License.
    +
    +"""
    +@file mlp_igd.py_in
    +
    +@brief Multilayer perceptron using IGD: Driver functions
    +
    +@namespace mlp_igd
    +"""
    +import plpy
    +
    +from utilities.control import MinWarning
    +from utilities.utilities import add_postfix
    +from utilities.utilities import py_list_to_sql_string
    +from utilities.utilities import extract_keyvalue_params
    +from utilities.utilities import _assert
    +from utilities.utilities import unique_string
    +from utilities.utilities import strip_end_quotes
    +
    +from utilities.validate_args import cols_in_tbl_valid
    +from utilities.validate_args import input_tbl_valid
    +from utilities.validate_args import is_var_valid
    +from utilities.validate_args import output_tbl_valid
    +from utilities.validate_args import get_expr_type
    +from utilities.validate_args import array_col_has_same_dimension
    +from utilities.validate_args import array_col_dimension
    +
    +
    +def mlp(schema_madlib, source_table, output_table, independent_varname,
    +        dependent_varname, hidden_layer_sizes,
    +        optimizer_param_str, activation, is_classification, **kwargs):
    +    """
    +    Args:
    +        @param schema_madlib
    +        @param source_table
    +        @param output_table
    +        @param independent_varname
    +        @param dependent_varname
    +        @param hidden_layer_sizes
    +        @param optimizer_param_str
    +
    +    Returns:
    +        None
    +    """
    +    with MinWarning('info'):
    +        optimizer_params = _get_optimizer_params(optimizer_param_str or "")
    +        _validate_args(source_table, output_table, independent_varname,
    +                       dependent_varname, hidden_layer_sizes,
    +                       optimizer_params, is_classification)
    +
    +        current_iteration = 1
    +        prev_state = None
    +        tolerance = optimizer_params["tolerance"]
    +        n_iterations = optimizer_params["n_iterations"]
    +        step_size = optimizer_params["step_size"]
    +        n_tries = optimizer_params["n_tries"]
    +        activation_name = _get_activation_function_name(activation)
    +        activation_index = _get_activation_index(activation_name)
    +        num_input_nodes = array_col_dimension(source_table, 
independent_varname)
    +        num_output_nodes = 0
    +        classes = []
    +        dependent_type = get_expr_type(dependent_varname, source_table)
    +        original_dependent_varname = dependent_varname
    +
    +        if(is_classification):
    +            dependent_variable_sql = """
    +                SELECT DISTINCT {dependent_varname}
    +                FROM {source_table}
    +                """.format(dependent_varname=dependent_varname,
    +                           source_table=source_table)
    +            labels = plpy.execute(dependent_variable_sql)
    +            one_hot_dependent_varname = 'ARRAY['
    +            num_output_nodes = len(labels)
    +            for x in labels:
    +                label = _format_label(x[dependent_varname])
    +                classes.append(label)
    +                one_hot_dependent_varname += dependent_varname + "=" + 
str(label) + ","
    +            # Remove the last comma
    +            one_hot_dependent_varname = one_hot_dependent_varname[:-1]
    +            one_hot_dependent_varname += ']::integer[]'
    +            dependent_varname = one_hot_dependent_varname
    +        if(not is_classification):
    +            if "[]" not in dependent_type:
    +                dependent_varname = "ARRAY[" + dependent_varname + "]"
    +            num_output_nodes = array_col_dimension(source_table, 
dependent_varname)
    +        layer_sizes = [num_input_nodes] + hidden_layer_sizes + 
[num_output_nodes]
    +
    +        while True:
    +            if prev_state:
    +                prev_state_str = py_list_to_sql_string(prev_state, 
array_type="double precision")
    +            else:
    +                prev_state_str = "(NULL)::DOUBLE PRECISION[]"
    +            train_sql = """
    +                SELECT
    +                    {schema_madlib}.mlp_igd_step(
    +                        ({independent_varname})::DOUBLE PRECISION[],
    +                        ({dependent_varname})::DOUBLE PRECISION[],
    +                        {prev_state},
    +                        {layer_sizes},
    +                        ({step_size})::FLOAT8,
    +                        {activation},
    +                        {is_classification}) as curr_state
    +                FROM {source_table} AS _src
    +                """.format(schema_madlib=schema_madlib,
    +                           independent_varname=independent_varname,
    +                           dependent_varname=dependent_varname,
    +                           prev_state=prev_state_str,
    +                           # C++ uses double internally
    +                           layer_sizes=py_list_to_sql_string(layer_sizes,
    +                                                             
array_type="double precision"),
    +                           step_size=step_size,
    +                           source_table=source_table,
    +                           activation=activation_index,
    +                           is_classification=int(is_classification))
    +            curr_state = plpy.execute(train_sql)[0]["curr_state"]
    +            dist_sql = """
    +                SELECT {schema_madlib}.internal_mlp_igd_distance(
    +                        {prev_state},
    +                        {curr_state}) as state_dist
    +                """.format(schema_madlib=schema_madlib,
    +                           prev_state=prev_state_str,
    +                           curr_state=py_list_to_sql_string(curr_state, 
"double precision"),
    +                           tolerance=tolerance)
    +            state_dist = plpy.execute(dist_sql)[0]["state_dist"]
    +            if ((state_dist and state_dist < tolerance) or
    +                    current_iteration > n_iterations):
    +                break
    +            prev_state = curr_state
    +            # plpy.info("Iteration: 
"+str(current_iteration)+"/"+str(n_iterations))
    +            current_iteration += 1
    +        _build_model_table(schema_madlib, output_table, curr_state, 
n_iterations)
    +        layer_sizes_str=py_list_to_sql_string(layer_sizes, 
array_type="integer")
    +        classes_str=py_list_to_sql_string([strip_end_quotes(cl, "'") for 
cl in classes],
    +                                          array_type=dependent_type)
    +        # TODO validation for summary
    +        summary_table_creation_query = """
    +            CREATE TABLE {output_table}_summary(
    +                source_table TEXT,
    +                independent_varname TEXT,
    +                dependent_varname TEXT,
    +                tolerance FLOAT,
    +                step_size FLOAT,
    +                n_iterations INTEGER,
    +                n_tries INTEGER,
    +                layer_sizes INTEGER[],
    +                activation_function TEXT,
    +                is_classification BOOLEAN,
    +                classes {dependent_type}[]
    +            )""".format(output_table=output_table,
    +                        dependent_type=dependent_type)
    +
    +        summary_table_update_query = """
    +            INSERT INTO {output_table}_summary VALUES(
    +                '{source_table}',
    +                '{independent_varname}',
    +                '{original_dependent_varname}',
    +                {tolerance},
    +                {step_size},
    +                {n_iterations},
    +                {n_tries},
    +                {layer_sizes_str},
    +                '{activation_name}',
    +                {is_classification},
    +                {classes_str}
    +            )
    +            """.format(**locals())
    +        plpy.execute(summary_table_creation_query)
    +        plpy.execute(summary_table_update_query)
    +# ----------------------------------------------------------------------
    +
    +
    +def _build_model_table(schema_madlib, output_table, final_state, 
n_iterations):
    +    final_state_str = py_list_to_sql_string(final_state, 
array_type="double precision")
    +
    +    model_table_query = """
    +        CREATE TABLE {output_table} AS
    +            SELECT
    +                (result).coeff AS coeff,
    +                (result).loss  AS loss,
    +                {n_iterations} AS num_iterations
    +                -- (result).num_rows_processed     AS num_rows_processed,
    +                -- n_tuples_including_nulls - (result).num_rows_processed
    +            FROM (
    +                SELECT
    +                    {schema_madlib}.internal_mlp_igd_result(
    +                        {final_state_str}
    +                    ) AS result
    +            ) rel_state_subq
    +        """.format(**locals())
    +    plpy.execute(model_table_query)
    +# ----------------------------------------------------------------------
    +
    +
    +def _get_optimizer_params(param_str):
    +    params_defaults = {
    +        "step_size": (0.001, float),
    +        "n_iterations": (100, int),
    +        "n_tries": (1, int),
    +        "tolerance": (0.001, float),
    +    }
    +    param_defaults = dict([(k, v[0]) for k, v in params_defaults.items()])
    +    param_types = dict([(k, v[1]) for k, v in params_defaults.items()])
    +
    +    if not param_str:
    +        return param_defaults
    +
    +    name_value = extract_keyvalue_params(param_str, param_types, 
param_defaults,
    +                                         ignore_invalid=True)
    +    return name_value
    +# ----------------------------------------------------------------------
    +
    +
    +def _validate_args_classification(source_table, output_table, 
independent_varname,
    +                                  dependent_varname, hidden_layer_sizes,
    +                                  optimizer_params):
    +    expr_type = get_expr_type(dependent_varname, source_table)
    +    int_types = ['integer', 'smallint', 'bigint']
    +    text_types = ['text', 'varchar', 'character varying', 'char', 
'character']
    +    boolean_types = ['boolean']
    +    _assert("[]" in expr_type or expr_type in int_types + text_types + 
boolean_types,
    +            "Dependent variable column should refer to an "
    +            "integer, boolean, text, varchar, or character type.")
    +# ----------------------------------------------------------------------
    +
    +
    +def _validate_args_regression(source_table, output_table, 
independent_varname,
    +                              dependent_varname, hidden_layer_sizes,
    +                              optimizer_params):
    +    expr_type = get_expr_type(dependent_varname, source_table)
    +    int_types = ['integer', 'smallint', 'bigint']
    +    float_types = ['double precision', 'real']
    +    _assert("[]" in expr_type or expr_type in int_types + float_types,
    +            "Dependent variable column should refer to an array or numeric 
type")
    +    if("[]" in expr_type):
    +        _assert(array_col_has_same_dimension(source_table, 
dependent_varname),
    +                "Dependent variable column should refer to arrays of the 
same length")
    +# ----------------------------------------------------------------------
    +
    +
    +def _validate_args(source_table, output_table, independent_varname,
    +                   dependent_varname, hidden_layer_sizes,
    +                   optimizer_params, is_classification):
    +    """
    +    Args:
    +        @param kwargs
    +
    +    Returns:
    +
    +    """
    +    input_tbl_valid(source_table, "MLP")
    +    output_tbl_valid(output_table, "MLP")
    +    output_tbl_valid(output_table+"_summary", "MLP")
    +    _assert(is_var_valid(source_table, independent_varname),
    +            "MLP error: invalid independent_varname "
    +            "('{independent_varname}') for source_table "
    +            
"({source_table})!".format(independent_varname=independent_varname,
    +                                       source_table=source_table))
    +
    +    _assert(is_var_valid(source_table, dependent_varname),
    +            "MLP error: invalid dependent_varname "
    +            "('{dependent_varname}') for source_table "
    +            "({source_table})!".format(dependent_varname=dependent_varname,
    +                                       source_table=source_table))
    +    _assert(hidden_layer_sizes is not None,
    +            "hidden_layer_sizes may not be null")
    +    _assert(type(hidden_layer_sizes) is list,
    +            "hidden_layer_sizes must be an array of integers")
    +    _assert(all(type(value) is int for value in hidden_layer_sizes),
    +            "MLP error: Hidden layers sizes must be integers")
    +    _assert(all(value >= 0 for value in hidden_layer_sizes),
    +            "MLP error: Hidden layers sizes must be greater than 0.")
    +    _assert(optimizer_params["tolerance"] >= 0,
    +            "MLP error: Tolerance should be greater than or equal to 0.")
    +    _assert(optimizer_params["n_tries"] >= 1,
    +            "MLP error: Number of tries should be greater than or equal to 
1")
    +    _assert(optimizer_params["n_iterations"] >= 1,
    +            "MLP error: Number of iterations should be greater than or 
equal to 1")
    +    _assert(optimizer_params["step_size"] > 0,
    +            "MLP error: Stepsize should be greater than 0.")
    +    _assert("[]" in get_expr_type(independent_varname, source_table),
    +            "Independent variable column should refer to an array")
    +    _assert(array_col_has_same_dimension(source_table, 
independent_varname),
    +            "Independent variable column should refer to arrays of the 
same length")
    +
    +    if is_classification:
    +        _validate_args_classification(source_table, output_table, 
independent_varname,
    +                                      dependent_varname, 
hidden_layer_sizes,
    +                                      optimizer_params)
    +    else:
    +        _validate_args_regression(source_table, output_table, 
independent_varname,
    +                                  dependent_varname, hidden_layer_sizes,
    +                                  optimizer_params)
    +# ----------------------------------------------------------------------
    +
    +
    +def _get_activation_function_name(activation_function):
    +    if not activation_function:
    +        activation_function = 'sigmoid'
    +    else:
    +        # Add non-linear kernels below after implementing them.
    +        supported_activation_function = ['sigmoid', 'tanh', 'relu']
    +        try:
    +            # allow user to specify a prefix substring of
    +            # supported kernels. This works because the supported
    +            # kernels have unique prefixes.
    +            activation_function = next(x for x in 
supported_activation_function
    +                                       if 
x.startswith(activation_function))
    +        except StopIteration:
    +            # next() returns a StopIteration if no element found
    +            plpy.error("MLP Error: Invalid activation function: "
    +                       "{0}. Supported activation functions are ({1})"
    +                       .format(activation_function, 
','.join(sorted(supported_activation_function))))
    +    return activation_function
    +# 
------------------------------------------------------------------------------
    +
    +
    +def _get_activation_index(activation_name):
    +    table = {"relu": 0, "sigmoid": 1, "tanh": 2}
    +    return table[activation_name]
    +
    +
    +def _format_label(label):
    +    if type(label) is str:
    +        return "'" + label + "'"
    +    return label
    +# -------------------------------------------------------------------------
    +
    +
    +def mlp_predict(schema_madlib, model_table, data_table,
    +                id_col_name, output_table,
    +                pred_type='response', **kwargs):
    +    """ Score new observations using a trained neural network
    +
    +    @param schema_madlib Name of the schema where MADlib is installed
    +    @param model_table Name of learned model
    +    @param data_table Name of table/view containing the data
    +                          points to be scored
    +    @param id_col_name Name of column in source_table containing
    +                       (integer) identifier for data point
    +    @param output_table Name of table to store the results
    +    @param pred_type: str, The type of output required:
    +                    'response' gives the actual response values,
    +                    'prob' gives the probability of the classes in a
    +                  For regression, only type='response' is defined.
    +    """
    +    # model table
    +    input_tbl_valid(model_table, 'MLP')
    +    cols_in_tbl_valid(model_table, ['coeff'], 'MLP')
    +    # summary table
    +    summary_table = add_postfix(model_table, "_summary")
    +    input_tbl_valid(summary_table, 'MLP')
    +    cols_in_tbl_valid(summary_table,
    +                      ['dependent_varname', 'independent_varname',
    +                       'activation_function',
    +                       'tolerance', 'step_size','n_iterations',
    +                       'n_tries', 'classes', 'layer_sizes', 
'source_table'],
    +                      'MLP')
    +
    +    # read necessary info from summary
    +    summary = plpy.execute("SELECT * FROM {0}".format(summary_table))[0]
    +    coeff = py_list_to_sql_string(plpy.execute("SELECT * FROM 
{0}".format(model_table))[0]["coeff"])
    +    dependent_varname = summary['dependent_varname']
    +    independent_varname = summary['independent_varname']
    +    source_table = summary['source_table']
    +    activation_function = 
_get_activation_index(summary['activation_function'])
    +    layer_sizes = py_list_to_sql_string(summary['layer_sizes'], 
array_type="DOUBLE PRECISION")
    +    is_classification = int(summary["is_classification"])
    +    is_response = int(pred_type=='response')
    +
    +    pred_name = ('"prob_{0}"' if pred_type == "prob" else
    +                 '"estimated_{0}"').format(dependent_varname.replace('"', 
'').strip())
    +
    +    input_tbl_valid(data_table, 'MLP')
    +
    +    _assert(is_var_valid(data_table, independent_varname),
    +            "MLP Error: independent_varname ('{0}') is invalid for 
data_table ({1})".
    +            format(independent_varname, data_table))
    +    _assert(id_col_name is not None, "MLP Error: id_col_name is NULL")
    +    _assert(is_var_valid(data_table, id_col_name),
    +            "MLP Error: id_col_name ('{0}') is invalid for {1}".
    +            format(id_col_name, data_table))
    +    output_tbl_valid(output_table, 'MLP')
    +    # optimizer_param_dict = _get_optimizer_params(optimizer_params)
    +
    +    with MinWarning("warning"):
    +        header = "CREATE TABLE " + output_table + " AS "
    +        # Regression
    +        if not is_classification:
    +            dependent_type = get_expr_type(dependent_varname, source_table)
    +            unnest_if_not_array = ""
    +            # Return the same type as the user provided.  Internally we 
always use an array, but
    +            # if they provided a scaler, unnest it for the user
    +            if("[]" not in dependent_type):
    +                unnest_if_not_array = "UNNEST"
    +            sql = header + """
    +                SELECT {id_col_name},
    +                       
{unnest_if_not_array}({schema_madlib}.internal_predict_mlp(
    +                            {coeff},
    +                            {independent_varname}::DOUBLE PRECISION[],
    +                            {is_classification},
    +                            {activation_function},
    +                            {layer_sizes},
    +                            {is_response}
    +                        )) as {pred_name}
    +                FROM {data_table}
    +                """
    +        else:
    +            summary_query = """
    +            SELECT classes FROM {0}_summary
    +            """.format(model_table)
    +            classes = plpy.execute(summary_query)[0]['classes']
    +            if pred_type == "response":
    +                # This join is to recover the class name from the summary 
table, as prediction just returns an index
    +                classes_with_index_table = unique_string()
    +                classes_table = unique_string()
    +                sql = header + """
    +                        SELECT
    +                             q.{id_col_name}
    +                            ,(ARRAY{classes})[pred_idx[1]+1] as {pred_name}
    +                        FROM (
    +                             SELECT
    +                                {id_col_name},
    +                                {schema_madlib}.internal_predict_mlp(
    +                                        {coeff}::DOUBLE PRECISION[],
    +                                        {independent_varname}::DOUBLE 
PRECISION[],
    +                                        {is_classification},
    +                                        {activation_function},
    +                                        {layer_sizes},
    +                                        {is_response}
    +                                        )
    +                               as pred_idx
    +                            FROM {data_table}
    +                        ) q
    +                    """
    +            else:
    +                # Incomplete
    +                intermediate_col = unique_string()
    +                score_format = ',\n'.join([
    +                    '{interim}[{j}] as "estimated_prob_{c}"'.
    +                    format(j=i + 1, c=c.strip(' "'), 
interim=intermediate_col)
    +                        for i, c in enumerate(classes)])
    +                sql = header + """
    +                    SELECT
    +                        {id_col_name},
    +                        {score_format}
    +                        FROM (
    +                            SELECT {id_col_name},
    +                                   
{schema_madlib}.internal_predict_mlp_output(
    +                                       {coeff}::DOUBLE PRECISION[],
    +                                       {independent_varname}::DOUBLE 
PRECISION[],
    +                                       {is_classification},
    +                                       {activation_function},
    +                                       {layer_sizes},
    +                                       {is_response}
    +                                       )::TEXT[]
    +                                            AS {intermediate_col}
    +                            FROM {data_table}
    +                        ) q
    +                    """
    +#TODO add join for validation
    +#  as s {join_str} {model} as m {using_str}
    +    sql = sql.format(**locals())
    +    with MinWarning('warning'):
    +        plpy.execute(sql)
    +
    +    pass
    +# ----------------------------------------------------------------------
    +
    +def mlp_help(schema_madlib, message, is_classification):
    +    method = 'mlp_classification' if is_classification else 
'mlp_regression'
    +    # TODO
    +    int_types = ['integer', 'smallint', 'bigint']
    +    text_types = ['text', 'varchar', 'character varying', 'char', 
'character']
    +    boolean_types = ['boolean']
    +    supported_types = " " * 33 + ", ".join(text_types) + "\n" + " " * 33 + 
", ".join(int_types + boolean_types)
    +    label_description_classification = "Name of a column which specifies 
label.\n" + " " * 33 + "Supported types are:\n" + supported_types
    +    label_description_regression = "Dependent variable. May be an array 
for multiple\n" +\
    +        " " * 33 + "regression or the name of a column which is any\n" + " 
" * 33 + "numeric type for single regression"
    +    label_description = label_description_classification if 
is_classification else label_description_regression
    +    args = dict(schema_madlib=schema_madlib, method=method, 
label_description=label_description)
    +
    +    summary = """
    +    ----------------------------------------------------------------
    +                            SUMMARY
    +    ----------------------------------------------------------------
    +    Multi Layer Perceptron (MLP) is a model for regression and
    +    classification
    +
    +    Also called "vanilla neural networks", they consist of several
    +    fully connected hidden layers with non-linear activation
    +    functions.
    +
    +    For more details on function usage:
    +        SELECT {schema_madlib}.{method}('usage')
    +
    +    For a small example on using the function:
    +        SELECT {schema_madlib}.{method}('example')""".format(**args)
    +
    +    usage = """
    +    
---------------------------------------------------------------------------
    +                                    USAGE
    +    
---------------------------------------------------------------------------
    +    SELECT {schema_madlib}.{method}(
    +        source_table,         -- name of input table
    +        output_table,         -- name of output model table
    +        independent_varname,  -- name of independent variable
    +        dependent_varname,    -- {label_description}
    +        hidden_layer_sizes,   -- Array of integers indicating the
    +                                 number of hidden units per layer.
    +                                 Length equal to the number of hidden 
layers.
    +        optimizer_params,     -- optional, default NULL
    +                                 parameters for optimization in
    +                                 a comma-separated string of key-value 
pairs.
    +
    +            step_size DOUBLE PRECISION, -- Default: 0.001
    +                                           Learning rate
    +            n_iterations INTEGER,       -- Default: 100
    +                                           Number of iterations per try
    +            n_tries INTEGER,            -- Default: 1
    +                                           Total number of training cycles,
    +                                           with random initializations to 
avoid
    +                                           local minima.
    +            tolerance DOUBLE PRECISION, -- Default: 0.001
    +                                           If the distance in loss between
    +                                           two iterations is less than the
    +                                           tolerance training will stop, 
even if
    +                                           n_iterations has not been 
reached
    +
    +        activation            -- optional, default: 'sigmoid'.
    +                                 supported activations: 'relu', 'sigmoid',
    +                                 and 'tanh'
    +    );
    +
    +
    +    
---------------------------------------------------------------------------
    +                                    OUTPUT
    +    
---------------------------------------------------------------------------
    +    The model table produced by MLP contains the following columns:
    +
    +    coeffs             -- Flat array containing the weights of the neural 
net
    +
    +    loss               -- The total loss over the training data. Cross 
entropy
    +                          for classification and MSE for regression
    +
    +    num_iterations     -- The total number of training iterations
    +
    +    """.format(**args)
    +
    +    regression_example = """
    +    - Create input table
    +
    +    CREATE TABLE lin_housing_wi (id serial, x float8[], grp_by_col int, y 
float8);
    +    COPY lin_housing_wi (x, grp_by_col, y) FROM STDIN NULL '?' DELIMITER 
'|';
    +    
{1,0.00632,18.00,2.310,0,0.5380,6.5750,65.20,4.0900,1,296.0,15.30,396.90,4.98} 
| 1 | 24.00
    +    
{1,0.02731,0.00,7.070,0,0.4690,6.4210,78.90,4.9671,2,242.0,17.80,396.90,9.14} | 
1 | 21.60
    +    
{1,0.02729,0.00,7.070,0,0.4690,7.1850,61.10,4.9671,2,242.0,17.80,392.83,4.03} | 
1 | 34.70
    +    
{1,0.03237,0.00,2.180,0,0.4580,6.9980,45.80,6.0622,3,222.0,18.70,394.63,2.94} | 
1 | 33.40
    +    
{1,0.06905,0.00,2.180,0,0.4580,7.1470,54.20,6.0622,3,222.0,18.70,396.90,5.33} | 
1 | 36.20
    +    
{1,0.02985,0.00,2.180,0,0.4580,6.4300,58.70,6.0622,3,222.0,18.70,394.12,5.21} | 
1 | 28.70
    +    
{1,0.08829,12.50,7.870,0,0.5240,6.0120,66.60,5.5605,5,311.0,15.20,395.60,12.43} 
| 1 | 22.90
    +    
{1,0.14455,12.50,7.870,0,0.5240,6.1720,96.10,5.9505,5,311.0,15.20,396.90,19.15} 
| 1 | 27.10
    +    
{1,0.21124,12.50,7.870,0,0.5240,5.6310,100.00,6.0821,5,311.0,15.20,386.63,29.93}
 | 1 | 16.50
    +    
{1,0.17004,12.50,7.870,0,0.5240,6.0040,85.90,6.5921,5,311.0,15.20,386.71,17.10} 
| 1 | 18.90
    +    
{1,0.22489,12.50,7.870,0,0.5240,6.3770,94.30,6.3467,5,311.0,15.20,392.52,20.45} 
| 1 | 15.00
    +    
{1,0.11747,12.50,7.870,0,0.5240,6.0090,82.90,6.2267,5,311.0,15.20,396.90,13.27} 
| 1 | 18.90
    +    
{1,0.09378,12.50,7.870,0,0.5240,5.8890,39.00,5.4509,5,311.0,15.20,390.50,15.71} 
| 1 | 21.70
    +    \.
    +
    +    - Generate a multilayer perception with a two hidden layers of 5 units
    +    each. Use the x column as the independent variables, and use the class
    +    column as the classification. Set the tolerance to 0 so that 300
    +    iterations will be run. Use a sigmoid activation function.
    +    The model will be written to mlp_regress_result.
    +
    +    SELECT mlp_regression(
    +        'lin_housing_wi',           -- Source table
    +        'mlp_regress_result',  -- Desination table
    +        'x',                        -- Independent variable
    +        'y',                        -- Dependent variable
    +        ARRAY[5,5],                 -- Number of hidden units per layer
    +        'step_size=0.007,
    +        n_iterations=300,
    +        tolerance=0',
    +        'sigmoid');                 -- Activation
    +
    +    """
    +
    +    classification_example = """
    +    -- Create input table
    +
    +    CREATE TABLE iris_data(
    +        id integer,
    +        attributes numeric[],
    +        class_text varchar,
    +        class integer
    +    );
    +
    +    INSERT INTO iris_data VALUES
    +    (1,ARRAY[5.1,3.5,1.4,0.2],'Iris-setosa',1),
    +    (2,ARRAY[4.9,3.0,1.4,0.2],'Iris-setosa',1),
    +    (3,ARRAY[4.7,3.2,1.3,0.2],'Iris-setosa',1),
    +    (4,ARRAY[4.6,3.1,1.5,0.2],'Iris-setosa',1),
    +    (5,ARRAY[5.0,3.6,1.4,0.2],'Iris-setosa',1),
    +    (6,ARRAY[5.4,3.9,1.7,0.4],'Iris-setosa',1),
    +    (7,ARRAY[4.6,3.4,1.4,0.3],'Iris-setosa',1),
    +    (8,ARRAY[5.0,3.4,1.5,0.2],'Iris-setosa',1),
    +    (9,ARRAY[4.4,2.9,1.4,0.2],'Iris-setosa',1),
    +    (10,ARRAY[4.9,3.1,1.5,0.1],'Iris-setosa',1),
    +    (11,ARRAY[7.0,3.2,4.7,1.4],'Iris-versicolor',2),
    +    (12,ARRAY[6.4,3.2,4.5,1.5],'Iris-versicolor',2),
    +    (13,ARRAY[6.9,3.1,4.9,1.5],'Iris-versicolor',2),
    +    (14,ARRAY[5.5,2.3,4.0,1.3],'Iris-versicolor',2),
    +    (15,ARRAY[6.5,2.8,4.6,1.5],'Iris-versicolor',2),
    +    (16,ARRAY[5.7,2.8,4.5,1.3],'Iris-versicolor',2),
    +    (17,ARRAY[6.3,3.3,4.7,1.6],'Iris-versicolor',2),
    +    (18,ARRAY[4.9,2.4,3.3,1.0],'Iris-versicolor',2),
    +    (19,ARRAY[6.6,2.9,4.6,1.3],'Iris-versicolor',2),
    +    (20,ARRAY[5.2,2.7,3.9,1.4],'Iris-versicolor',2),
    --- End diff --
    
    In the INSERT example, the trailing comma (`,`) should be a semi-colon 
(`;`).


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at [email protected] or file a JIRA ticket
with INFRA.
---

Reply via email to