You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@madlib.apache.org by nk...@apache.org on 2024/02/26 19:28:51 UTC
(madlib) 03/05: PMML: Add dev-check tests for pmml export
This is an automated email from the ASF dual-hosted git repository.
nkak pushed a commit to branch madlib2-master
in repository https://gitbox.apache.org/repos/asf/madlib.git
commit 8a85d8e054da4014c36137097e00315c43f930e3
Author: Nikhil Kak <nk...@vmware.com>
AuthorDate: Fri Feb 16 13:34:15 2024 -0800
PMML: Add dev-check tests for pmml export
JIRA: MADLIB-1517
This commit introduces a new function named `test_pmml_output` which can be
used to test the output of the pmml function. It compares the output of
madlib's predict function with pypmml's predict function
* Added a pmml setup file that contains all the common datasets and functions
used by the pmml dev-check tests
* Added exhaustive tests to glm, linear and logistic. A future commit will add
more tests to other pmml modules
---
.../{pmml_glm_gamma.sql_in => pmml.setup.sql_in} | 322 +++++++++++++++++----
.../modules/pmml/test/pmml_check_fields.sql_in | 150 ++++++++++
.../modules/pmml/test/pmml_glm_binomial.sql_in | 178 ++++++------
.../modules/pmml/test/pmml_glm_gamma.sql_in | 145 ++++------
.../postgres/modules/pmml/test/pmml_glm_ig.sql_in | 128 ++++----
.../modules/pmml/test/pmml_glm_normal.sql_in | 171 ++++++-----
.../modules/pmml/test/pmml_glm_poisson.sql_in | 118 ++++----
.../pmml/test/pmml_glm_with_grouping.sql_in | 125 ++++++++
.../pmml/test/pmml_glm_with_name_spec.sql_in | 160 ++++++++++
.../postgres/modules/pmml/test/pmml_linear.sql_in | 91 ++++++
.../modules/pmml/test/pmml_logistic.sql_in | 159 ++++++++++
.../modules/pmml/test/pmml_multinom.sql_in | 25 +-
.../test/pmml_with_non_array_expression.sql_in | 94 ++++++
.../modules/pmml/test/table_to_pmml.sql_in | 197 -------------
14 files changed, 1406 insertions(+), 657 deletions(-)
diff --git a/src/ports/postgres/modules/pmml/test/pmml_glm_gamma.sql_in b/src/ports/postgres/modules/pmml/test/pmml.setup.sql_in
similarity index 50%
copy from src/ports/postgres/modules/pmml/test/pmml_glm_gamma.sql_in
copy to src/ports/postgres/modules/pmml/test/pmml.setup.sql_in
index e8b56066..dad6a03f 100644
--- a/src/ports/postgres/modules/pmml/test/pmml_glm_gamma.sql_in
+++ b/src/ports/postgres/modules/pmml/test/pmml.setup.sql_in
@@ -1,5 +1,55 @@
-DROP TABLE IF EXISTS abalone CASCADE;
+/* ----------------------------------------------------------------------- *//**
+ *
+ * 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.
+ *
+ *//* ----------------------------------------------------------------------- */
+
+ DROP TABLE IF EXISTS houses CASCADE;
+CREATE TABLE houses (
+ id SERIAL NOT NULL,
+ tax INTEGER,
+ bedroom REAL,
+ bath REAL,
+ price INTEGER,
+ size INTEGER,
+ lot INTEGER,
+ g1 CHAR(1),
+ g2 CHAR(1)
+);
+INSERT INTO houses(tax, bedroom, bath, price, size, lot, g1, g2) VALUES
+( 590, 2, 1, 50000, 770, 22100, 'A', 'z'),
+(1050, 3, 2, 85000, 1410, 12000, 'A', 'y'),
+(20, 3, 1, 22500, 1060, 3500 , 'A', 'y'),
+( 870, 2, 2, 90000, 1300, 17500, 'A', 'y'),
+(1320, 3, 2, 133000, 1500, 30000, 'A', 'y'),
+(1350, 2, 1, 90500, 820, 25700, 'A', 'x'),
+(2790, 3, 2.5, 260000, 2130, 25000, 'A', 'x'),
+( 680, 2, 1, 142500, 1170, 22000, 'A', 'x'),
+(1840, 3, 2, 160000, 1500, 19000, 'B', 'x'),
+(3680, 4, 2, 240000, 2790, 20000, 'B', 'y'),
+(1660, 3, 1, 87000, 1030, 17500, 'B', 'y'),
+(1620, 3, 2, 118600, 1250, 20000, 'A', 'y'),
+(3100, 3, 2, 140000, 1760, 38000, 'B', 'y'),
+(2070, 2, 3, 148000, 1550, 14000, 'B', 'y'),
+( 650, 3, 1.5, 65000, 1450, 12000, 'B', 'y');
+
+DROP TABLE IF EXISTS abalone CASCADE;
CREATE TABLE abalone (
id integer,
sex text,
@@ -76,88 +126,238 @@ INSERT INTO abalone VALUES
(3759, 'I', 0.525000000000000022, 0.400000000000000022, 0.140000000000000013, 0.605500000000000038, 0.260500000000000009, 0.107999999999999999, 0.209999999999999992, 9);
-DROP TABLE IF EXISTS abalone_out_inverse, abalone_out_inverse_summary;
-SELECT glm(
- 'abalone',
- 'abalone_out_inverse',
- 'rings',
- 'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
- 'family=gamma, link=inverse', NULL, 'max_iter=1000, tolerance=1e-16'
+DROP TABLE IF EXISTS warpbreaks CASCADE;
+CREATE TABLE warpbreaks(
+ id serial,
+ breaks integer,
+ wool char(1),
+ tension char(1),
+ g char(1)
);
-DROP TABLE IF EXISTS abalone_out_identity, abalone_out_identity_summary;
-SELECT glm(
- 'abalone',
- 'abalone_out_identity',
- 'rings',
- 'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
- 'family=gamma, link=identity', NULL, 'max_iter=1000, tolerance=1e-16'
-);
+INSERT INTO warpbreaks(breaks, wool, tension, g) VALUES
+(26, 'A', 'L', '1'),
+(30, 'A', 'L', '1'),
+(54, 'A', 'L', '1'),
+(25, 'A', 'L', '1'),
+(70, 'A', 'L', '1'),
+(52, 'A', 'L', '1'),
+(51, 'A', 'L', '1'),
+(26, 'A', 'L', '1'),
+(67, 'A', 'L', '1'),
+(18, 'A', 'M', '1'),
+(21, 'A', 'M', '1'),
+(29, 'A', 'M', '1'),
+(17, 'A', 'M', '1'),
+(12, 'A', 'M', '1'),
+(18, 'A', 'M', '1'),
+(35, 'A', 'M', '1'),
+(30, 'A', 'M', '1'),
+(36, 'A', 'M', '1'),
+(36, 'A', 'H', '0'),
+(21, 'A', 'H', '0'),
+(24, 'A', 'H', '0'),
+(18, 'A', 'H', '0'),
+(10, 'A', 'H', '0'),
+(43, 'A', 'H', '0'),
+(28, 'A', 'H', '0'),
+(15, 'A', 'H', '0'),
+(26, 'A', 'H', '0'),
+(27, 'B', 'L', '0'),
+(14, 'B', 'L', '0'),
+(29, 'B', 'L', '0'),
+(19, 'B', 'L', '0'),
+(29, 'B', 'L', '0'),
+(31, 'B', 'L', '0'),
+(41, 'B', 'L', '0'),
+(20, 'B', 'L', '1'),
+(44, 'B', 'L', '1'),
+(42, 'B', 'M', '1'),
+(26, 'B', 'M', '1'),
+(19, 'B', 'M', '1'),
+(16, 'B', 'M', '1'),
+(39, 'B', 'M', '1'),
+(28, 'B', 'M', '1'),
+(21, 'B', 'M', '1'),
+(39, 'B', 'M', '1'),
+(29, 'B', 'M', '1'),
+(20, 'B', 'H', '1'),
+(21, 'B', 'H', '1'),
+(24, 'B', 'H', '1'),
+(17, 'B', 'H', '1'),
+(13, 'B', 'H', '1'),
+(15, 'B', 'H', '1'),
+(15, 'B', 'H', '1'),
+(16, 'B', 'H', '1'),
+(28, 'B', 'H', '1');
-DROP TABLE IF EXISTS abalone_out_log, abalone_out_log_summary;
-SELECT glm(
- 'abalone',
- 'abalone_out_log',
- 'rings',
- 'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
- 'family=gamma, link=log', NULL, 'max_iter=1000, tolerance=1e-16'
-);
+DROP TABLE IF EXISTS warpbreaks_dummy;
+SELECT create_indicator_variables('warpbreaks', 'warpbreaks_dummy', 'wool,tension');
-DROP TABLE IF EXISTS abalone_out_log_grp, abalone_out_log_grp_summary;
-SELECT glm(
- 'abalone',
- 'abalone_out_log_grp',
- 'rings',
- 'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
- 'family=gamma, link=log', 'sex', 'max_iter=1000, tolerance=1e-16'
+DROP TABLE IF EXISTS "Patients";
+CREATE TABLE "Patients" (
+ id integer NOT NULL,
+ "Second_attack" integer,
+ "Treatment" integer,
+ trait_anxiety integer,
+ g1 char(1),
+ g2 char(1)
);
+INSERT INTO "Patients"(ID, "Second_attack", "Treatment", trait_anxiety, g1, g2) VALUES
+( 1, 1, 1, 70, 'A', 'x'),
+( 2, 1, 1, 80, 'A', 'y'),
+( 3, 1, 1, 50, 'A', 'y'),
+( 4, 1, 0, 60, 'A', 'y'),
+( 5, 1, 0, 40, 'A', 'y'),
+( 6, 1, 0, 65, 'A', 'x'),
+( 7, 1, 0, 75, 'A', 'x'),
+( 8, 1, 0, 80, 'B', 'x'),
+( 9, 1, 0, 70, 'A', 'x'),
+(10, 1, 0, 60, 'A', 'z'),
+(11, 0, 1, 65, 'A', 'z'),
+(12, 0, 1, 50, 'B', 'y'),
+(13, 0, 1, 45, 'A', 'y'),
+(14, 0, 1, 35, 'A', 'z'),
+(15, 0, 1, 40, 'A', 'z'),
+(16, 0, 1, 50, 'A', 'z'),
+(17, 0, 0, 55, 'B', 'z'),
+(18, 0, 0, 45, 'B', 'z'),
+(19, 0, 0, 50, 'B', 'z'),
+(20, 0, 0, 60, 'B', 'z');
+/* ----------------------------------------------------------------------- *//**
+ *
+ * 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.
+ *
+ *//* ----------------------------------------------------------------------- */
+
+/**
+ * @brief Compares the madlib prediction output with pypmml prediction output.
+ * Assumes that the caller has already run madlib's predict function on the test table
+ * Creates a dictionary of the madlib results by querying the madlib_predict_table
+ * Calls the pmml function on the trained madlib table
+ * Loops through all the rows of the test table and FOR EACH ROW:
+ ** Gets the madlib prediction from the dict created above
+ ** Runs pypmml predict
+ ** Compares madlib and pypmml results
+ ** Throws an error if the values don't match
+ * @param test_table The test table which was used for madlib prediction. This table will be used for pmml prediction
+ * @param madlib_train_table The trained model table
+ * @param madlib_predict_table The madlib prediction table
+ * @param id_col id column in the test table used for uniquely identifying the rows for comparison
+ * @param madlib_prediction_metric Name of the column in madlib prediction table that contains the value to compare
+ * @param pypmml_prediction_metric Name of the key in pmml prediction dict that contains the value to compare
+ * @param grouping_col grouping col used during training
+ * @param name_spec name_spec to be passed to the madlib pmml function
+ * @returns
+ *
+ */
+CREATE OR REPLACE FUNCTION test_pmml_output(test_table TEXT, madlib_train_table TEXT, madlib_predict_table TEXT,
+ id_col TEXT, madlib_prediction_metric TEXT, pypmml_prediction_metric TEXT, grouping_col TEXT, name_spec TEXT) returns VOID as $$
+ # This function returns a key so that we can compare the results from the madlib prediction table with the pmml
+ # result that gets run on the test table
+ # The key of this dict is either just the 'id' or a combination of 'id' and all the grouping cold
+ def get_unique_key(input):
+ unique_key = [str(input[id_col])]
+ if grouping_col != '':
+ cols = grouping_col.split(',')
+ for col in cols:
+ unique_key.append(str(input[col]))
+ return ','.join(unique_key)
+
+ def are_results_different(madlib_result, pypmml_result):
+ from math import isnan, isinf
+ if isinstance(madlib_result, str):
+ return str(pypmml_result) != str(madlib_result)
+ elif isinstance(madlib_result, float) or isinstance(madlib_result, int):
+ if isinf(float(madlib_result)) or isnan(float(madlib_result)):
+ return True
+ if isinf(float(pypmml_result)) or isnan(float(pypmml_result)):
+ return True
+ tol = 1e-6
+ return abs(pypmml_result - madlib_result) > tol
+ return True
-SELECT pmml('abalone_out_inverse');
-SELECT pmml('abalone_out_log');
-SELECT pmml('abalone_out_identity');
-SELECT pmml('abalone_out_log_grp');
+ from pypmml import Model
-CREATE OR REPLACE FUNCTION count_expected_names(formula varchar, expected varchar[])
+ madlib_predict_output_table = plpy.execute("SELECT * from {}".format(madlib_predict_table))
+ madlib_predict_output = {}
+ for madlib_pred in madlib_predict_output_table:
+ madlib_predict_output[get_unique_key(madlib_pred)] = madlib_pred[madlib_prediction_metric]
+
+ #get madlib pmml output string
+ if name_spec == '':
+ pmml_query = "SELECT pmml('{}')".format(madlib_train_table)
+ else:
+ pmml_query = "SELECT pmml('{}','{}')".format(madlib_train_table, name_spec)
+ madlib_pmml_str = plpy.execute(pmml_query)[0]["pmml"]
+
+ # load pypmml model using madlib pmml string
+ pypmml_model = Model.fromString(madlib_pmml_str)
+
+ # load data and run pypmml predict
+ test_data = plpy.execute("SELECT * from {}".format(test_table))
+ for data in test_data:
+ madlib_result = madlib_predict_output[get_unique_key(data)]
+ pypmml_prediction = pypmml_model.predict(data)
+ if pypmml_prediction_metric not in pypmml_prediction:
+ plpy.error("Metric: '{}' does not exist in pypmml output: {}".format(pypmml_prediction_metric, pypmml_prediction))
+ pypmml_result = pypmml_prediction[pypmml_prediction_metric]
+ if are_results_different(madlib_result, pypmml_result):
+ plpy.info(madlib_pmml_str)
+ plpy.error("pmml comparison failed. input row: {}, metric to compare: {}, madlib result: {}, pypmml result: {}, detailed madlib output: {}, detailed pypmml output: {}".format(data, pypmml_prediction_metric, madlib_result, pypmml_result, madlib_predict_output, pypmml_prediction))
+$$ language plpython3u;
+
+CREATE OR REPLACE FUNCTION test_pmml_output(test_table TEXT, madlib_train_table TEXT, madlib_predict_table TEXT,
+ id_col TEXT, madlib_prediction_metric TEXT, pypmml_prediction_metric TEXT, grouping_col TEXT) returns VOID as $$
+ SELECT test_pmml_output(test_table, madlib_train_table, madlib_predict_table, id_col, madlib_prediction_metric, pypmml_prediction_metric, grouping_col, '')
+$$ language sql;
+
+CREATE OR REPLACE FUNCTION test_pmml_output(test_table TEXT, madlib_train_table TEXT, madlib_predict_table TEXT,
+ id_col TEXT, madlib_prediction_metric TEXT, pypmml_prediction_metric TEXT) returns VOID as $$
+ SELECT test_pmml_output(test_table, madlib_train_table, madlib_predict_table, id_col, madlib_prediction_metric, pypmml_prediction_metric, '', '')
+$$ language sql;
+
+
+CREATE OR REPLACE FUNCTION count_expected_names(madlib_train_table varchar, formula varchar, expected varchar[])
RETURNS bigint AS $$
SELECT count(distinct result.name)
FROM
(SELECT text(unnest(xpath('/n:PMML/n:DataDictionary/n:DataField/@name',
pmml_col, ARRAY[ARRAY['n', 'http://www.dmg.org/PMML-4_1']]))) AS name
- FROM (SELECT CASE WHEN $1 is NULL THEN pmml('abalone_out_inverse')
- ELSE pmml('abalone_out_inverse', $1)
- END AS pmml_col) abalone_out_inverse_pmml
+ FROM (SELECT CASE WHEN $2 is NULL THEN pmml(madlib_train_table)
+ ELSE pmml(madlib_train_table, $2)
+ END AS pmml_col) pmml_output
) result,
- (SELECT unnest($2) AS name) expected
+ (SELECT unnest($3) AS name) expected
WHERE expected.name = result.name;
$$ LANGUAGE sql;
-CREATE OR REPLACE FUNCTION count_expected_names(name_spec varchar[], expected varchar[])
+CREATE OR REPLACE FUNCTION count_expected_names(madlib_train_table varchar, name_spec varchar[], expected varchar[])
RETURNS bigint AS $$
SELECT count(distinct result.name)
FROM
(SELECT text(unnest(xpath('/n:PMML/n:DataDictionary/n:DataField/@name',
pmml_col, ARRAY[ARRAY['n', 'http://www.dmg.org/PMML-4_1']]))) AS name
- FROM (SELECT CASE WHEN $1 is NULL THEN pmml('abalone_out_inverse')
- ELSE pmml('abalone_out_inverse', $1)
- END AS pmml_col) abalone_out_inverse_pmml
+ FROM (SELECT CASE WHEN $2 is NULL THEN pmml(madlib_train_table)
+ ELSE pmml(madlib_train_table, $2)
+ END AS pmml_col) pmml_output
) result,
- (SELECT unnest($2) AS name) expected
+ (SELECT unnest($3) AS name) expected
WHERE expected.name = result.name;
$$ LANGUAGE sql;
-
-SELECT assert(
- count_expected_names(
- NULL,
- ARRAY['rings_pmml_prediction', '1', 'length', 'diameter', 'height', 'whole', 'shucked', 'viscera', 'shell']
- ) = 9,
- 'default case');
-
-SELECT assert(
- count_expected_names(
- 'rings ~ 1 + length + diameter + height',
- ARRAY['rings', '1', 'length', 'diameter', 'height']
- ) = 5,
- text(pmml('abalone_out_inverse',
- 'rings ~ 1 + length + diameter + height')));
-
diff --git a/src/ports/postgres/modules/pmml/test/pmml_check_fields.sql_in b/src/ports/postgres/modules/pmml/test/pmml_check_fields.sql_in
new file mode 100644
index 00000000..8381398a
--- /dev/null
+++ b/src/ports/postgres/modules/pmml/test/pmml_check_fields.sql_in
@@ -0,0 +1,150 @@
+/* ----------------------------------------------------------------------- *//**
+ *
+ * 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.
+ *
+ *//* ----------------------------------------------------------------------- */
+
+ \i m4_regexp(MADLIB_LIBRARY_PATH, `\(.*\)/lib',
+ `\1/../modules/pmml/test/pmml.setup.sql_in'
+)
+
+m4_changequote(`<!'', `!>'')
+
+--------------------- linear regression -----------------------
+DROP TABLE IF EXISTS linregr_model, linregr_model_summary;
+SELECT linregr_train(
+ 'houses',
+ 'linregr_model',
+ 'price',
+ 'array[1, bedroom, bath, size]',
+ 'g1, g2'
+);
+
+SELECT assert(
+ count_expected_names('linregr_model',
+ NULL,
+ ARRAY['price_pmml_prediction', 'bedroom', 'bath', 'size', 'g1', 'g2']
+ ) = 6,
+ text(pmml('linregr_model')));
+
+SELECT assert(
+ count_expected_names('linregr_model',
+ 'c.price ~ c.bedroom + c.bath + c.size',
+ ARRAY['c.price', 'c.bedroom', 'c.bath', 'c.size']
+ ) = 4,
+ text(pmml('linregr_model',
+ 'c.price ~ c.bedroom + c.bath + c.size')));
+
+SELECT assert(
+ count_expected_names('linregr_model',
+ '{c.price, c.bedroom, c.bath, c.size}'::varchar[],
+ ARRAY['c.price', 'c.bedroom', 'c.bath', 'c.size']
+ ) = 4,
+ text(pmml('linregr_model',
+ 'c.price ~ c.bedroom + c.bath + c.size')));
+
+SELECT assert(
+ count_expected_names('linregr_model',
+ '{c.price, c.bedroom, c.bath, c.size}',
+ ARRAY['c.price', 'c.bedroom', 'c.bath', 'c.size']
+ ) = 4,
+ text(pmml('linregr_model',
+ 'c.price ~ c.bedroom + c.bath + c.size')));
+
+SELECT assert(
+ count_expected_names('linregr_model',
+ 'c.bedroom + c.bath + c.size',
+ ARRAY['price', 'c.bedroom', 'c.bath', 'c.size']
+ ) = 4,
+ text(pmml('linregr_model',
+ 'c.bedroom + c.bath + c.size')));
+
+SELECT assert(
+ count_expected_names('linregr_model',
+ 'c.bedroom, c.bath, c.size',
+ ARRAY['price', 'c.bedroom', 'c.bath', 'c.size']
+ ) = 4,
+ text(pmml('linregr_model',
+ 'c.bedroom, c.bath, c.size')));
+
+--------------------- logistic regression -----------------------
+DROP TABLE IF EXISTS logregr_model, logregr_model_summary;
+SELECT logregr_train(
+ '"Patients"',
+ 'logregr_model',
+ '"Second_attack"',
+ 'ARRAY[1, "Treatment", trait_anxiety]',
+ NULL,
+ 20,
+ 'irls'
+);
+
+SELECT assert(
+ count_expected_names('logregr_model',
+ NULL,
+ ARRAY['Second_attack_pmml_prediction', 'Treatment', 'trait_anxiety']
+ ) = 3,
+ text(pmml('logregr_model')));
+
+SELECT assert(
+ count_expected_names('logregr_model',
+ 'c.second_attack ~ c.treatment + c.anxiety',
+ ARRAY['c.second_attack', 'c.treatment', 'c.anxiety']
+ ) = 3,
+ text(pmml('logregr_model',
+ 'c.second_attack ~ c.treatment + c.anxiety')));
+
+SELECT assert(
+ count_expected_names('logregr_model',
+ '{c.second_attack, c.treatment, c.anxiety}'::varchar[],
+ ARRAY['c.second_attack', 'c.treatment', 'c.anxiety']
+ ) = 3,
+ text(pmml('logregr_model',
+ '{c.second_attack, c.treatment, c.anxiety}')));
+
+SELECT assert(
+ count_expected_names('logregr_model',
+ '{c.second_attack, c.treatment, c.anxiety}',
+ ARRAY['c.second_attack', 'c.treatment', 'c.anxiety']
+ ) = 3,
+ text(pmml('logregr_model',
+ '{c.second_attack, c.treatment, c.anxiety}')));
+
+SELECT assert(
+ count_expected_names('logregr_model',
+ 'c.treatment + c.anxiety',
+ ARRAY['Second_attack', 'c.treatment', 'c.anxiety']
+ ) = 3,
+ text(pmml('logregr_model',
+ 'c.treatment + c.anxiety')));
+
+SELECT assert(
+ count_expected_names('logregr_model',
+ 'c.treatment, c.anxiety',
+ ARRAY['Second_attack', 'c.treatment', 'c.anxiety']
+ ) = 3,
+ text(pmml('logregr_model',
+ 'c.treatment, c.anxiety')));
+
+SELECT assert(
+ count_expected_names('logregr_model',
+ 'c.treatment, c.trait_anxiety',
+ ARRAY['Second_attack', 'c.treatment', 'c.trait_anxiety']
+ ) = 3,
+ text(pmml('logregr_model',
+ 'c.treatment, c.trait_anxiety')));
diff --git a/src/ports/postgres/modules/pmml/test/pmml_glm_binomial.sql_in b/src/ports/postgres/modules/pmml/test/pmml_glm_binomial.sql_in
index b874bd9e..3c17815c 100644
--- a/src/ports/postgres/modules/pmml/test/pmml_glm_binomial.sql_in
+++ b/src/ports/postgres/modules/pmml/test/pmml_glm_binomial.sql_in
@@ -1,100 +1,110 @@
-DROP TABLE IF EXISTS abalone CASCADE;
-
-CREATE TABLE abalone (
- id integer,
- sex text,
- length double precision,
- diameter double precision,
- height double precision,
- whole double precision,
- shucked double precision,
- viscera double precision,
- shell double precision,
- rings integer
-);
+\i m4_regexp(MADLIB_LIBRARY_PATH,
+ `\(.*\)/lib',
+ `\1/../modules/pmml/test/pmml.setup.sql_in'
+)
+
+m4_changequote(`<!'', `!>'')
-INSERT INTO abalone VALUES
-(3151, 'F', 0.655000000000000027, 0.505000000000000004, 0.165000000000000008, 1.36699999999999999, 0.583500000000000019, 0.351499999999999979, 0.396000000000000019, 10),
-(2026, 'F', 0.550000000000000044, 0.469999999999999973, 0.149999999999999994, 0.920499999999999985, 0.381000000000000005, 0.243499999999999994, 0.267500000000000016, 10),
-(3751, 'I', 0.434999999999999998, 0.375, 0.110000000000000001, 0.41549999999999998, 0.170000000000000012, 0.0759999999999999981, 0.14499999999999999, 8),
-(720, 'I', 0.149999999999999994, 0.100000000000000006, 0.0250000000000000014, 0.0149999999999999994, 0.00449999999999999966, 0.00400000000000000008, 0.0050000000000000001, 2),
-(1635, 'F', 0.574999999999999956, 0.469999999999999973, 0.154999999999999999, 1.1160000000000001, 0.509000000000000008, 0.237999999999999989, 0.340000000000000024, 10),
-(2648, 'I', 0.5, 0.390000000000000013, 0.125, 0.582999999999999963, 0.293999999999999984, 0.132000000000000006, 0.160500000000000004, 8),
-(1796, 'F', 0.57999999999999996, 0.429999999999999993, 0.170000000000000012, 1.47999999999999998, 0.65349999999999997, 0.32400000000000001, 0.41549999999999998, 10),
-(209, 'F', 0.525000000000000022, 0.41499999999999998, 0.170000000000000012, 0.832500000000000018, 0.275500000000000023, 0.168500000000000011, 0.309999999999999998, 13),
-(1451, 'I', 0.455000000000000016, 0.33500000000000002, 0.135000000000000009, 0.501000000000000001, 0.274000000000000021, 0.0995000000000000051, 0.106499999999999997, 7),
-(1108, 'I', 0.510000000000000009, 0.380000000000000004, 0.115000000000000005, 0.515499999999999958, 0.214999999999999997, 0.113500000000000004, 0.166000000000000009, 8),
-(3675, 'F', 0.594999999999999973, 0.450000000000000011, 0.165000000000000008, 1.08099999999999996, 0.489999999999999991, 0.252500000000000002, 0.279000000000000026, 12),
-(2108, 'F', 0.675000000000000044, 0.550000000000000044, 0.179999999999999993, 1.68849999999999989, 0.562000000000000055, 0.370499999999999996, 0.599999999999999978, 15),
-(3312, 'F', 0.479999999999999982, 0.380000000000000004, 0.135000000000000009, 0.507000000000000006, 0.191500000000000004, 0.13650000000000001, 0.154999999999999999, 12),
-(882, 'M', 0.655000000000000027, 0.520000000000000018, 0.165000000000000008, 1.40949999999999998, 0.585999999999999965, 0.290999999999999981, 0.405000000000000027, 9),
-(3402, 'M', 0.479999999999999982, 0.395000000000000018, 0.149999999999999994, 0.681499999999999995, 0.214499999999999996, 0.140500000000000014, 0.2495, 18),
-(829, 'I', 0.409999999999999976, 0.325000000000000011, 0.100000000000000006, 0.394000000000000017, 0.20799999999999999, 0.0655000000000000027, 0.105999999999999997, 6),
-(1305, 'M', 0.535000000000000031, 0.434999999999999998, 0.149999999999999994, 0.716999999999999971, 0.347499999999999976, 0.14449999999999999, 0.194000000000000006, 9),
-(3613, 'M', 0.599999999999999978, 0.46000000000000002, 0.179999999999999993, 1.1399999999999999, 0.422999999999999987, 0.257500000000000007, 0.364999999999999991, 10),
-(1068, 'I', 0.340000000000000024, 0.265000000000000013, 0.0800000000000000017, 0.201500000000000012, 0.0899999999999999967, 0.0475000000000000006, 0.0550000000000000003, 5),
-(2446, 'M', 0.5, 0.380000000000000004, 0.135000000000000009, 0.583500000000000019, 0.22950000000000001, 0.126500000000000001, 0.179999999999999993, 12),
-(1393, 'M', 0.635000000000000009, 0.474999999999999978, 0.170000000000000012, 1.19350000000000001, 0.520499999999999963, 0.269500000000000017, 0.366499999999999992, 10),
-(359, 'M', 0.744999999999999996, 0.584999999999999964, 0.214999999999999997, 2.49900000000000011, 0.92649999999999999, 0.471999999999999975, 0.699999999999999956, 17),
-(549, 'F', 0.564999999999999947, 0.450000000000000011, 0.160000000000000003, 0.79500000000000004, 0.360499999999999987, 0.155499999999999999, 0.23000000000000001, 12),
-(1154, 'F', 0.599999999999999978, 0.474999999999999978, 0.160000000000000003, 1.02649999999999997, 0.484999999999999987, 0.2495, 0.256500000000000006, 9),
-(1790, 'F', 0.54500000000000004, 0.385000000000000009, 0.149999999999999994, 1.11850000000000005, 0.542499999999999982, 0.244499999999999995, 0.284499999999999975, 9),
-(3703, 'F', 0.665000000000000036, 0.540000000000000036, 0.195000000000000007, 1.76400000000000001, 0.850500000000000034, 0.361499999999999988, 0.469999999999999973, 11),
-(1962, 'F', 0.655000000000000027, 0.515000000000000013, 0.179999999999999993, 1.41199999999999992, 0.619500000000000051, 0.248499999999999999, 0.496999999999999997, 11),
-(1665, 'I', 0.604999999999999982, 0.469999999999999973, 0.14499999999999999, 0.802499999999999991, 0.379000000000000004, 0.226500000000000007, 0.220000000000000001, 9),
-(635, 'M', 0.359999999999999987, 0.294999999999999984, 0.100000000000000006, 0.210499999999999993, 0.0660000000000000031, 0.0524999999999999981, 0.0749999999999999972, 9),
-(3901, 'M', 0.445000000000000007, 0.344999999999999973, 0.140000000000000013, 0.475999999999999979, 0.205499999999999988, 0.101500000000000007, 0.108499999999999999, 15),
-(2734, 'I', 0.41499999999999998, 0.33500000000000002, 0.100000000000000006, 0.357999999999999985, 0.169000000000000011, 0.067000000000000004, 0.104999999999999996, 7),
-(3856, 'M', 0.409999999999999976, 0.33500000000000002, 0.115000000000000005, 0.440500000000000003, 0.190000000000000002, 0.0850000000000000061, 0.135000000000000009, 8),
-(827, 'I', 0.395000000000000018, 0.28999999999999998, 0.0950000000000000011, 0.303999999999999992, 0.127000000000000002, 0.0840000000000000052, 0.076999999999999999, 6),
-(3381, 'I', 0.190000000000000002, 0.130000000000000004, 0.0449999999999999983, 0.0264999999999999993, 0.00899999999999999932, 0.0050000000000000001, 0.00899999999999999932, 5),
-(3972, 'I', 0.400000000000000022, 0.294999999999999984, 0.0950000000000000011, 0.252000000000000002, 0.110500000000000001, 0.0575000000000000025, 0.0660000000000000031, 6),
-(1155, 'M', 0.599999999999999978, 0.455000000000000016, 0.170000000000000012, 1.1915, 0.695999999999999952, 0.239499999999999991, 0.239999999999999991, 8),
-(3467, 'M', 0.640000000000000013, 0.5, 0.170000000000000012, 1.4544999999999999, 0.642000000000000015, 0.357499999999999984, 0.353999999999999981, 9),
-(2433, 'F', 0.609999999999999987, 0.484999999999999987, 0.165000000000000008, 1.08699999999999997, 0.425499999999999989, 0.232000000000000012, 0.380000000000000004, 11),
-(552, 'I', 0.614999999999999991, 0.489999999999999991, 0.154999999999999999, 0.988500000000000045, 0.41449999999999998, 0.195000000000000007, 0.344999999999999973, 13),
-(1425, 'F', 0.729999999999999982, 0.57999999999999996, 0.190000000000000002, 1.73750000000000004, 0.678499999999999992, 0.434499999999999997, 0.520000000000000018, 11),
-(2402, 'F', 0.584999999999999964, 0.41499999999999998, 0.154999999999999999, 0.69850000000000001, 0.299999999999999989, 0.145999999999999991, 0.195000000000000007, 12),
-(1748, 'F', 0.699999999999999956, 0.535000000000000031, 0.174999999999999989, 1.77299999999999991, 0.680499999999999994, 0.479999999999999982, 0.512000000000000011, 15),
-(3983, 'I', 0.57999999999999996, 0.434999999999999998, 0.149999999999999994, 0.891499999999999959, 0.362999999999999989, 0.192500000000000004, 0.251500000000000001, 6),
-(335, 'F', 0.739999999999999991, 0.599999999999999978, 0.195000000000000007, 1.97399999999999998, 0.597999999999999976, 0.408499999999999974, 0.709999999999999964, 16),
-(1587, 'I', 0.515000000000000013, 0.349999999999999978, 0.104999999999999996, 0.474499999999999977, 0.212999999999999995, 0.122999999999999998, 0.127500000000000002, 10),
-(2448, 'I', 0.275000000000000022, 0.204999999999999988, 0.0800000000000000017, 0.096000000000000002, 0.0359999999999999973, 0.0184999999999999991, 0.0299999999999999989, 6),
-(1362, 'F', 0.604999999999999982, 0.474999999999999978, 0.174999999999999989, 1.07600000000000007, 0.463000000000000023, 0.219500000000000001, 0.33500000000000002, 9),
-(2799, 'M', 0.640000000000000013, 0.484999999999999987, 0.149999999999999994, 1.09800000000000009, 0.519499999999999962, 0.222000000000000003, 0.317500000000000004, 10),
-(1413, 'F', 0.67000000000000004, 0.505000000000000004, 0.174999999999999989, 1.01449999999999996, 0.4375, 0.271000000000000019, 0.3745, 10),
-(1739, 'F', 0.67000000000000004, 0.540000000000000036, 0.195000000000000007, 1.61899999999999999, 0.739999999999999991, 0.330500000000000016, 0.465000000000000024, 11),
-(1152, 'M', 0.584999999999999964, 0.465000000000000024, 0.160000000000000003, 0.955500000000000016, 0.45950000000000002, 0.235999999999999988, 0.265000000000000013, 7),
-(2427, 'I', 0.564999999999999947, 0.434999999999999998, 0.154999999999999999, 0.782000000000000028, 0.271500000000000019, 0.16800000000000001, 0.284999999999999976, 14),
-(1777, 'M', 0.484999999999999987, 0.369999999999999996, 0.154999999999999999, 0.967999999999999972, 0.418999999999999984, 0.245499999999999996, 0.236499999999999988, 9),
-(3294, 'M', 0.574999999999999956, 0.455000000000000016, 0.184999999999999998, 1.15599999999999992, 0.552499999999999991, 0.242999999999999994, 0.294999999999999984, 13),
-(1403, 'M', 0.650000000000000022, 0.510000000000000009, 0.190000000000000002, 1.54200000000000004, 0.715500000000000025, 0.373499999999999999, 0.375, 9),
-(2256, 'M', 0.510000000000000009, 0.395000000000000018, 0.14499999999999999, 0.61850000000000005, 0.215999999999999998, 0.138500000000000012, 0.239999999999999991, 12),
-(3984, 'F', 0.584999999999999964, 0.450000000000000011, 0.125, 0.873999999999999999, 0.354499999999999982, 0.20749999999999999, 0.225000000000000006, 6),
-(1116, 'M', 0.525000000000000022, 0.405000000000000027, 0.119999999999999996, 0.755499999999999949, 0.3755, 0.155499999999999999, 0.201000000000000012, 9),
-(1366, 'M', 0.609999999999999987, 0.474999999999999978, 0.170000000000000012, 1.02649999999999997, 0.434999999999999998, 0.233500000000000013, 0.303499999999999992, 10),
-(3759, 'I', 0.525000000000000022, 0.400000000000000022, 0.140000000000000013, 0.605500000000000038, 0.260500000000000009, 0.107999999999999999, 0.209999999999999992, 9);
-
-
-DROP TABLE IF EXISTS abalone_probit_out, abalone_probit_out_summary;
+----------------------- binomial with probit -------------------------------
+DROP TABLE IF EXISTS abalone_binomial_out, abalone_binomial_out_summary;
SELECT glm(
'abalone',
- 'abalone_probit_out',
+ 'abalone_binomial_out',
'rings < 10',
'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
'family=binomial, link=probit', NULL, 'max_iter=1000, tolerance=1e-16'
);
-DROP TABLE IF EXISTS abalone_logit_out, abalone_logit_out_summary;
+-- Test probabilities
+DROP TABLE IF EXISTS glm_predict_binomial_probit_out; CREATE TABLE glm_predict_binomial_probit_out as SELECT id, glm_predict(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'probit')
+FROM abalone_binomial_out, abalone;
+SELECT test_pmml_output('abalone', 'abalone_binomial_out', 'glm_predict_binomial_probit_out', 'id', 'glm_predict', 'probability_true');
+
+-- Test output category
+DROP TABLE IF EXISTS glm_predict_binomial_probit_out; CREATE TABLE glm_predict_binomial_probit_out as SELECT id, glm_predict_binomial(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'probit')
+FROM abalone_binomial_out, abalone;
+SELECT test_pmml_output('abalone', 'abalone_binomial_out', 'glm_predict_binomial_probit_out', 'id', 'glm_predict_binomial', 'predicted_(rings < 10)_pmml_prediction');
+
+----------------------- binomial with logit -------------------------------
+DROP TABLE IF EXISTS abalone_binomial_logit_out, abalone_binomial_logit_out_summary;
SELECT glm(
'abalone',
- 'abalone_logit_out',
+ 'abalone_binomial_logit_out',
'rings < 10',
- 'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
+ 'ARRAY[1.0, length, diameter, height, whole, shucked, viscera, shell]',
'family=binomial, link=logit', NULL, 'max_iter=1000, tolerance=1e-16'
);
+-- Test probabilities
+DROP TABLE IF EXISTS glm_predict_binomial_logit_out; CREATE TABLE glm_predict_binomial_logit_out as SELECT id, glm_predict(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'logit')
+FROM abalone_binomial_logit_out, abalone;
+SELECT test_pmml_output('abalone', 'abalone_binomial_logit_out', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true');
+
+-- Test output category
+DROP TABLE IF EXISTS glm_predict_binomial_logit_out; CREATE TABLE glm_predict_binomial_logit_out as SELECT id, glm_predict_binomial(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'logit')
+FROM abalone_binomial_logit_out, abalone;
+SELECT test_pmml_output('abalone', 'abalone_binomial_logit_out', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_(rings < 10)_pmml_prediction');
+
+
+------------------------------------------------ Without intercept --------------------------------------------------
+
+----------------------- binomial with probit and grouping col-------------------------------
+DROP TABLE IF EXISTS abalone_binomial_nointercept_out, abalone_binomial_nointercept_out_summary;
+SELECT glm(
+ 'abalone',
+ 'abalone_binomial_nointercept_out',
+ 'rings < 10',
+ 'ARRAY[length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=binomial, link=probit', NULL, 'max_iter=1000, tolerance=1e-16'
+);
+
+-- Test probabilities
+DROP TABLE IF EXISTS glm_predict_binomial_probit_out; CREATE TABLE glm_predict_binomial_probit_out as SELECT id, glm_predict(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'probit')
+FROM abalone_binomial_nointercept_out, abalone;
+SELECT test_pmml_output('abalone', 'abalone_binomial_nointercept_out', 'glm_predict_binomial_probit_out', 'id', 'glm_predict', 'probability_true');
+
+-- Test output category
+DROP TABLE IF EXISTS glm_predict_binomial_probit_out; CREATE TABLE glm_predict_binomial_probit_out as SELECT id, glm_predict_binomial(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'probit')
+FROM abalone_binomial_nointercept_out, abalone;
+SELECT test_pmml_output('abalone', 'abalone_binomial_nointercept_out', 'glm_predict_binomial_probit_out', 'id', 'glm_predict_binomial', 'predicted_(rings < 10)_pmml_prediction');
+
+----------------------- binomial with logit -------------------------------
+DROP TABLE IF EXISTS abalone_binomial_nointercept_logit_out, abalone_binomial_nointercept_logit_out_summary;
+SELECT glm(
+ 'abalone',
+ 'abalone_binomial_nointercept_logit_out',
+ 'rings < 10',
+ 'ARRAY[length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=binomial, link=logit', NULL, 'max_iter=1000, tolerance=1e-16'
+);
+
+-- Test probabilities
+DROP TABLE IF EXISTS glm_predict_binomial_logit_out; CREATE TABLE glm_predict_binomial_logit_out as SELECT id, glm_predict(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'logit')
+FROM abalone_binomial_nointercept_logit_out, abalone;
+SELECT test_pmml_output('abalone', 'abalone_binomial_nointercept_logit_out', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true');
+
+-- Test output category
+DROP TABLE IF EXISTS glm_predict_binomial_logit_out; CREATE TABLE glm_predict_binomial_logit_out as SELECT id, glm_predict_binomial(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'logit')
+FROM abalone_binomial_nointercept_logit_out, abalone;
+SELECT test_pmml_output('abalone', 'abalone_binomial_nointercept_logit_out', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_(rings < 10)_pmml_prediction');
+
+
+------------------------------------------------ with 0 intercept --------------------------------------------------
+DROP TABLE IF EXISTS abalone_binomial_zerointercept_out, abalone_binomial_zerointercept_out_summary;
+SELECT glm(
+ 'abalone',
+ 'abalone_binomial_zerointercept_out',
+ 'rings < 10',
+ 'ARRAY[0, length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=binomial, link=probit', NULL, 'max_iter=1000, tolerance=1e-16'
+);
-SELECT pmml('abalone_probit_out');
-SELECT pmml('abalone_logit_out');
+-- Test probabilities
+DROP TABLE IF EXISTS glm_predict_binomial_probit_out; CREATE TABLE glm_predict_binomial_probit_out as SELECT id, glm_predict(coef, ARRAY[0, length, diameter, height, whole, shucked, viscera, shell], 'probit')
+FROM abalone_binomial_zerointercept_out, abalone;
+SELECT test_pmml_output('abalone', 'abalone_binomial_zerointercept_out', 'glm_predict_binomial_probit_out', 'id', 'glm_predict', 'probability_true');
+-- Test output category
+DROP TABLE IF EXISTS glm_predict_binomial_probit_out; CREATE TABLE glm_predict_binomial_probit_out as SELECT id, glm_predict_binomial(coef, ARRAY[0, length, diameter, height, whole, shucked, viscera, shell], 'probit')
+FROM abalone_binomial_zerointercept_out, abalone;
+SELECT test_pmml_output('abalone', 'abalone_binomial_zerointercept_out', 'glm_predict_binomial_probit_out', 'id', 'glm_predict_binomial', 'predicted_(rings < 10)_pmml_prediction');
diff --git a/src/ports/postgres/modules/pmml/test/pmml_glm_gamma.sql_in b/src/ports/postgres/modules/pmml/test/pmml_glm_gamma.sql_in
index e8b56066..e10a827d 100644
--- a/src/ports/postgres/modules/pmml/test/pmml_glm_gamma.sql_in
+++ b/src/ports/postgres/modules/pmml/test/pmml_glm_gamma.sql_in
@@ -1,81 +1,11 @@
-DROP TABLE IF EXISTS abalone CASCADE;
-
-CREATE TABLE abalone (
- id integer,
- sex text,
- length double precision,
- diameter double precision,
- height double precision,
- whole double precision,
- shucked double precision,
- viscera double precision,
- shell double precision,
- rings integer
-);
-
-INSERT INTO abalone VALUES
-(3151, 'F', 0.655000000000000027, 0.505000000000000004, 0.165000000000000008, 1.36699999999999999, 0.583500000000000019, 0.351499999999999979, 0.396000000000000019, 10),
-(2026, 'F', 0.550000000000000044, 0.469999999999999973, 0.149999999999999994, 0.920499999999999985, 0.381000000000000005, 0.243499999999999994, 0.267500000000000016, 10),
-(3751, 'I', 0.434999999999999998, 0.375, 0.110000000000000001, 0.41549999999999998, 0.170000000000000012, 0.0759999999999999981, 0.14499999999999999, 8),
-(720, 'I', 0.149999999999999994, 0.100000000000000006, 0.0250000000000000014, 0.0149999999999999994, 0.00449999999999999966, 0.00400000000000000008, 0.0050000000000000001, 2),
-(1635, 'F', 0.574999999999999956, 0.469999999999999973, 0.154999999999999999, 1.1160000000000001, 0.509000000000000008, 0.237999999999999989, 0.340000000000000024, 10),
-(2648, 'I', 0.5, 0.390000000000000013, 0.125, 0.582999999999999963, 0.293999999999999984, 0.132000000000000006, 0.160500000000000004, 8),
-(1796, 'F', 0.57999999999999996, 0.429999999999999993, 0.170000000000000012, 1.47999999999999998, 0.65349999999999997, 0.32400000000000001, 0.41549999999999998, 10),
-(209, 'F', 0.525000000000000022, 0.41499999999999998, 0.170000000000000012, 0.832500000000000018, 0.275500000000000023, 0.168500000000000011, 0.309999999999999998, 13),
-(1451, 'I', 0.455000000000000016, 0.33500000000000002, 0.135000000000000009, 0.501000000000000001, 0.274000000000000021, 0.0995000000000000051, 0.106499999999999997, 7),
-(1108, 'I', 0.510000000000000009, 0.380000000000000004, 0.115000000000000005, 0.515499999999999958, 0.214999999999999997, 0.113500000000000004, 0.166000000000000009, 8),
-(3675, 'F', 0.594999999999999973, 0.450000000000000011, 0.165000000000000008, 1.08099999999999996, 0.489999999999999991, 0.252500000000000002, 0.279000000000000026, 12),
-(2108, 'F', 0.675000000000000044, 0.550000000000000044, 0.179999999999999993, 1.68849999999999989, 0.562000000000000055, 0.370499999999999996, 0.599999999999999978, 15),
-(3312, 'F', 0.479999999999999982, 0.380000000000000004, 0.135000000000000009, 0.507000000000000006, 0.191500000000000004, 0.13650000000000001, 0.154999999999999999, 12),
-(882, 'M', 0.655000000000000027, 0.520000000000000018, 0.165000000000000008, 1.40949999999999998, 0.585999999999999965, 0.290999999999999981, 0.405000000000000027, 9),
-(3402, 'M', 0.479999999999999982, 0.395000000000000018, 0.149999999999999994, 0.681499999999999995, 0.214499999999999996, 0.140500000000000014, 0.2495, 18),
-(829, 'I', 0.409999999999999976, 0.325000000000000011, 0.100000000000000006, 0.394000000000000017, 0.20799999999999999, 0.0655000000000000027, 0.105999999999999997, 6),
-(1305, 'M', 0.535000000000000031, 0.434999999999999998, 0.149999999999999994, 0.716999999999999971, 0.347499999999999976, 0.14449999999999999, 0.194000000000000006, 9),
-(3613, 'M', 0.599999999999999978, 0.46000000000000002, 0.179999999999999993, 1.1399999999999999, 0.422999999999999987, 0.257500000000000007, 0.364999999999999991, 10),
-(1068, 'I', 0.340000000000000024, 0.265000000000000013, 0.0800000000000000017, 0.201500000000000012, 0.0899999999999999967, 0.0475000000000000006, 0.0550000000000000003, 5),
-(2446, 'M', 0.5, 0.380000000000000004, 0.135000000000000009, 0.583500000000000019, 0.22950000000000001, 0.126500000000000001, 0.179999999999999993, 12),
-(1393, 'M', 0.635000000000000009, 0.474999999999999978, 0.170000000000000012, 1.19350000000000001, 0.520499999999999963, 0.269500000000000017, 0.366499999999999992, 10),
-(359, 'M', 0.744999999999999996, 0.584999999999999964, 0.214999999999999997, 2.49900000000000011, 0.92649999999999999, 0.471999999999999975, 0.699999999999999956, 17),
-(549, 'F', 0.564999999999999947, 0.450000000000000011, 0.160000000000000003, 0.79500000000000004, 0.360499999999999987, 0.155499999999999999, 0.23000000000000001, 12),
-(1154, 'F', 0.599999999999999978, 0.474999999999999978, 0.160000000000000003, 1.02649999999999997, 0.484999999999999987, 0.2495, 0.256500000000000006, 9),
-(1790, 'F', 0.54500000000000004, 0.385000000000000009, 0.149999999999999994, 1.11850000000000005, 0.542499999999999982, 0.244499999999999995, 0.284499999999999975, 9),
-(3703, 'F', 0.665000000000000036, 0.540000000000000036, 0.195000000000000007, 1.76400000000000001, 0.850500000000000034, 0.361499999999999988, 0.469999999999999973, 11),
-(1962, 'F', 0.655000000000000027, 0.515000000000000013, 0.179999999999999993, 1.41199999999999992, 0.619500000000000051, 0.248499999999999999, 0.496999999999999997, 11),
-(1665, 'I', 0.604999999999999982, 0.469999999999999973, 0.14499999999999999, 0.802499999999999991, 0.379000000000000004, 0.226500000000000007, 0.220000000000000001, 9),
-(635, 'M', 0.359999999999999987, 0.294999999999999984, 0.100000000000000006, 0.210499999999999993, 0.0660000000000000031, 0.0524999999999999981, 0.0749999999999999972, 9),
-(3901, 'M', 0.445000000000000007, 0.344999999999999973, 0.140000000000000013, 0.475999999999999979, 0.205499999999999988, 0.101500000000000007, 0.108499999999999999, 15),
-(2734, 'I', 0.41499999999999998, 0.33500000000000002, 0.100000000000000006, 0.357999999999999985, 0.169000000000000011, 0.067000000000000004, 0.104999999999999996, 7),
-(3856, 'M', 0.409999999999999976, 0.33500000000000002, 0.115000000000000005, 0.440500000000000003, 0.190000000000000002, 0.0850000000000000061, 0.135000000000000009, 8),
-(827, 'I', 0.395000000000000018, 0.28999999999999998, 0.0950000000000000011, 0.303999999999999992, 0.127000000000000002, 0.0840000000000000052, 0.076999999999999999, 6),
-(3381, 'I', 0.190000000000000002, 0.130000000000000004, 0.0449999999999999983, 0.0264999999999999993, 0.00899999999999999932, 0.0050000000000000001, 0.00899999999999999932, 5),
-(3972, 'I', 0.400000000000000022, 0.294999999999999984, 0.0950000000000000011, 0.252000000000000002, 0.110500000000000001, 0.0575000000000000025, 0.0660000000000000031, 6),
-(1155, 'M', 0.599999999999999978, 0.455000000000000016, 0.170000000000000012, 1.1915, 0.695999999999999952, 0.239499999999999991, 0.239999999999999991, 8),
-(3467, 'M', 0.640000000000000013, 0.5, 0.170000000000000012, 1.4544999999999999, 0.642000000000000015, 0.357499999999999984, 0.353999999999999981, 9),
-(2433, 'F', 0.609999999999999987, 0.484999999999999987, 0.165000000000000008, 1.08699999999999997, 0.425499999999999989, 0.232000000000000012, 0.380000000000000004, 11),
-(552, 'I', 0.614999999999999991, 0.489999999999999991, 0.154999999999999999, 0.988500000000000045, 0.41449999999999998, 0.195000000000000007, 0.344999999999999973, 13),
-(1425, 'F', 0.729999999999999982, 0.57999999999999996, 0.190000000000000002, 1.73750000000000004, 0.678499999999999992, 0.434499999999999997, 0.520000000000000018, 11),
-(2402, 'F', 0.584999999999999964, 0.41499999999999998, 0.154999999999999999, 0.69850000000000001, 0.299999999999999989, 0.145999999999999991, 0.195000000000000007, 12),
-(1748, 'F', 0.699999999999999956, 0.535000000000000031, 0.174999999999999989, 1.77299999999999991, 0.680499999999999994, 0.479999999999999982, 0.512000000000000011, 15),
-(3983, 'I', 0.57999999999999996, 0.434999999999999998, 0.149999999999999994, 0.891499999999999959, 0.362999999999999989, 0.192500000000000004, 0.251500000000000001, 6),
-(335, 'F', 0.739999999999999991, 0.599999999999999978, 0.195000000000000007, 1.97399999999999998, 0.597999999999999976, 0.408499999999999974, 0.709999999999999964, 16),
-(1587, 'I', 0.515000000000000013, 0.349999999999999978, 0.104999999999999996, 0.474499999999999977, 0.212999999999999995, 0.122999999999999998, 0.127500000000000002, 10),
-(2448, 'I', 0.275000000000000022, 0.204999999999999988, 0.0800000000000000017, 0.096000000000000002, 0.0359999999999999973, 0.0184999999999999991, 0.0299999999999999989, 6),
-(1362, 'F', 0.604999999999999982, 0.474999999999999978, 0.174999999999999989, 1.07600000000000007, 0.463000000000000023, 0.219500000000000001, 0.33500000000000002, 9),
-(2799, 'M', 0.640000000000000013, 0.484999999999999987, 0.149999999999999994, 1.09800000000000009, 0.519499999999999962, 0.222000000000000003, 0.317500000000000004, 10),
-(1413, 'F', 0.67000000000000004, 0.505000000000000004, 0.174999999999999989, 1.01449999999999996, 0.4375, 0.271000000000000019, 0.3745, 10),
-(1739, 'F', 0.67000000000000004, 0.540000000000000036, 0.195000000000000007, 1.61899999999999999, 0.739999999999999991, 0.330500000000000016, 0.465000000000000024, 11),
-(1152, 'M', 0.584999999999999964, 0.465000000000000024, 0.160000000000000003, 0.955500000000000016, 0.45950000000000002, 0.235999999999999988, 0.265000000000000013, 7),
-(2427, 'I', 0.564999999999999947, 0.434999999999999998, 0.154999999999999999, 0.782000000000000028, 0.271500000000000019, 0.16800000000000001, 0.284999999999999976, 14),
-(1777, 'M', 0.484999999999999987, 0.369999999999999996, 0.154999999999999999, 0.967999999999999972, 0.418999999999999984, 0.245499999999999996, 0.236499999999999988, 9),
-(3294, 'M', 0.574999999999999956, 0.455000000000000016, 0.184999999999999998, 1.15599999999999992, 0.552499999999999991, 0.242999999999999994, 0.294999999999999984, 13),
-(1403, 'M', 0.650000000000000022, 0.510000000000000009, 0.190000000000000002, 1.54200000000000004, 0.715500000000000025, 0.373499999999999999, 0.375, 9),
-(2256, 'M', 0.510000000000000009, 0.395000000000000018, 0.14499999999999999, 0.61850000000000005, 0.215999999999999998, 0.138500000000000012, 0.239999999999999991, 12),
-(3984, 'F', 0.584999999999999964, 0.450000000000000011, 0.125, 0.873999999999999999, 0.354499999999999982, 0.20749999999999999, 0.225000000000000006, 6),
-(1116, 'M', 0.525000000000000022, 0.405000000000000027, 0.119999999999999996, 0.755499999999999949, 0.3755, 0.155499999999999999, 0.201000000000000012, 9),
-(1366, 'M', 0.609999999999999987, 0.474999999999999978, 0.170000000000000012, 1.02649999999999997, 0.434999999999999998, 0.233500000000000013, 0.303499999999999992, 10),
-(3759, 'I', 0.525000000000000022, 0.400000000000000022, 0.140000000000000013, 0.605500000000000038, 0.260500000000000009, 0.107999999999999999, 0.209999999999999992, 9);
+\i m4_regexp(MADLIB_LIBRARY_PATH,
+ `\(.*\)/lib',
+ `\1/../modules/pmml/test/pmml.setup.sql_in'
+)
+m4_changequote(`<!', `!>'')
+-------------------------------------------------- With intercept -------------------------------------------------------------------------
DROP TABLE IF EXISTS abalone_out_inverse, abalone_out_inverse_summary;
SELECT glm(
'abalone',
@@ -84,6 +14,10 @@ SELECT glm(
'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
'family=gamma, link=inverse', NULL, 'max_iter=1000, tolerance=1e-16'
);
+DROP TABLE IF EXISTS glm_predict_gamma_out; CREATE TABLE glm_predict_gamma_out as SELECT id, glm_predict(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'inverse')
+FROM abalone_out_inverse, abalone;
+SELECT test_pmml_output('abalone', 'abalone_out_inverse', 'glm_predict_gamma_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
+
DROP TABLE IF EXISTS abalone_out_identity, abalone_out_identity_summary;
SELECT glm(
@@ -93,6 +27,10 @@ SELECT glm(
'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
'family=gamma, link=identity', NULL, 'max_iter=1000, tolerance=1e-16'
);
+DROP TABLE IF EXISTS glm_predict_gamma_out; CREATE TABLE glm_predict_gamma_out as SELECT id, glm_predict(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'identity')
+FROM abalone_out_identity, abalone;
+SELECT test_pmml_output('abalone', 'abalone_out_identity', 'glm_predict_gamma_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
+
DROP TABLE IF EXISTS abalone_out_log, abalone_out_log_summary;
SELECT glm(
@@ -102,21 +40,50 @@ SELECT glm(
'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
'family=gamma, link=log', NULL, 'max_iter=1000, tolerance=1e-16'
);
+DROP TABLE IF EXISTS glm_predict_gamma_out; CREATE TABLE glm_predict_gamma_out as SELECT id, glm_predict(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'log')
+FROM abalone_out_log, abalone;
+SELECT test_pmml_output('abalone', 'abalone_out_log', 'glm_predict_gamma_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
-DROP TABLE IF EXISTS abalone_out_log_grp, abalone_out_log_grp_summary;
+-------------------------------------------------- Without intercept -------------------------------------------------------------------------
+DROP TABLE IF EXISTS abalone_out_inverse_nointercept, abalone_out_inverse_nointercept_summary;
SELECT glm(
'abalone',
- 'abalone_out_log_grp',
+ 'abalone_out_inverse_nointercept',
'rings',
- 'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
- 'family=gamma, link=log', 'sex', 'max_iter=1000, tolerance=1e-16'
+ 'ARRAY[length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=gamma, link=inverse', NULL, 'max_iter=1000, tolerance=1e-16'
);
+DROP TABLE IF EXISTS glm_predict_gamma_out; CREATE TABLE glm_predict_gamma_out as SELECT id, glm_predict(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'inverse')
+FROM abalone_out_inverse_nointercept, abalone;
+SELECT test_pmml_output('abalone', 'abalone_out_inverse_nointercept', 'glm_predict_gamma_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
+
+DROP TABLE IF EXISTS abalone_out_identity_nointercept, abalone_out_identity_nointercept_summary;
+SELECT glm(
+ 'abalone',
+ 'abalone_out_identity_nointercept',
+ 'rings',
+ 'ARRAY[length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=gamma, link=identity', NULL, 'max_iter=1000, tolerance=1e-16'
+);
+DROP TABLE IF EXISTS glm_predict_gamma_out; CREATE TABLE glm_predict_gamma_out as SELECT id, glm_predict(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'identity')
+FROM abalone_out_identity_nointercept, abalone;
+SELECT test_pmml_output('abalone', 'abalone_out_identity_nointercept', 'glm_predict_gamma_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
+
+
+DROP TABLE IF EXISTS abalone_out_log_nointercept, abalone_out_log_nointercept_summary;
+SELECT glm(
+ 'abalone',
+ 'abalone_out_log_nointercept',
+ 'rings',
+ 'ARRAY[length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=gamma, link=log', NULL, 'max_iter=1000, tolerance=1e-16'
+);
+DROP TABLE IF EXISTS glm_predict_gamma_out; CREATE TABLE glm_predict_gamma_out as SELECT id, glm_predict(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'log')
+FROM abalone_out_log_nointercept, abalone;
+SELECT test_pmml_output('abalone', 'abalone_out_log_nointercept', 'glm_predict_gamma_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
-SELECT pmml('abalone_out_inverse');
-SELECT pmml('abalone_out_log');
-SELECT pmml('abalone_out_identity');
-SELECT pmml('abalone_out_log_grp');
+-------------------------------------- Test pmml output ----------------------------------------------------------------
CREATE OR REPLACE FUNCTION count_expected_names(formula varchar, expected varchar[])
RETURNS bigint AS $$
@@ -149,15 +116,15 @@ $$ LANGUAGE sql;
SELECT assert(
count_expected_names(
NULL,
- ARRAY['rings_pmml_prediction', '1', 'length', 'diameter', 'height', 'whole', 'shucked', 'viscera', 'shell']
- ) = 9,
+ ARRAY['rings_pmml_prediction', 'length', 'diameter', 'height', 'whole', 'shucked', 'viscera', 'shell']
+ ) = 8,
'default case');
SELECT assert(
count_expected_names(
- 'rings ~ 1 + length + diameter + height',
- ARRAY['rings', '1', 'length', 'diameter', 'height']
- ) = 5,
+ 'rings ~ length + diameter + height',
+ ARRAY['rings', 'length', 'diameter', 'height']
+ ) = 4,
text(pmml('abalone_out_inverse',
'rings ~ 1 + length + diameter + height')));
diff --git a/src/ports/postgres/modules/pmml/test/pmml_glm_ig.sql_in b/src/ports/postgres/modules/pmml/test/pmml_glm_ig.sql_in
index ee07de53..a99b3056 100644
--- a/src/ports/postgres/modules/pmml/test/pmml_glm_ig.sql_in
+++ b/src/ports/postgres/modules/pmml/test/pmml_glm_ig.sql_in
@@ -1,81 +1,11 @@
-DROP TABLE IF EXISTS abalone;
-
-CREATE TABLE abalone (
- id integer,
- sex text,
- length double precision,
- diameter double precision,
- height double precision,
- whole double precision,
- shucked double precision,
- viscera double precision,
- shell double precision,
- rings integer
-);
-
-INSERT INTO abalone VALUES
-(3151, 'F', 0.655000000000000027, 0.505000000000000004, 0.165000000000000008, 1.36699999999999999, 0.583500000000000019, 0.351499999999999979, 0.396000000000000019, 10),
-(2026, 'F', 0.550000000000000044, 0.469999999999999973, 0.149999999999999994, 0.920499999999999985, 0.381000000000000005, 0.243499999999999994, 0.267500000000000016, 10),
-(3751, 'I', 0.434999999999999998, 0.375, 0.110000000000000001, 0.41549999999999998, 0.170000000000000012, 0.0759999999999999981, 0.14499999999999999, 8),
-(720, 'I', 0.149999999999999994, 0.100000000000000006, 0.0250000000000000014, 0.0149999999999999994, 0.00449999999999999966, 0.00400000000000000008, 0.0050000000000000001, 2),
-(1635, 'F', 0.574999999999999956, 0.469999999999999973, 0.154999999999999999, 1.1160000000000001, 0.509000000000000008, 0.237999999999999989, 0.340000000000000024, 10),
-(2648, 'I', 0.5, 0.390000000000000013, 0.125, 0.582999999999999963, 0.293999999999999984, 0.132000000000000006, 0.160500000000000004, 8),
-(1796, 'F', 0.57999999999999996, 0.429999999999999993, 0.170000000000000012, 1.47999999999999998, 0.65349999999999997, 0.32400000000000001, 0.41549999999999998, 10),
-(209, 'F', 0.525000000000000022, 0.41499999999999998, 0.170000000000000012, 0.832500000000000018, 0.275500000000000023, 0.168500000000000011, 0.309999999999999998, 13),
-(1451, 'I', 0.455000000000000016, 0.33500000000000002, 0.135000000000000009, 0.501000000000000001, 0.274000000000000021, 0.0995000000000000051, 0.106499999999999997, 7),
-(1108, 'I', 0.510000000000000009, 0.380000000000000004, 0.115000000000000005, 0.515499999999999958, 0.214999999999999997, 0.113500000000000004, 0.166000000000000009, 8),
-(3675, 'F', 0.594999999999999973, 0.450000000000000011, 0.165000000000000008, 1.08099999999999996, 0.489999999999999991, 0.252500000000000002, 0.279000000000000026, 12),
-(2108, 'F', 0.675000000000000044, 0.550000000000000044, 0.179999999999999993, 1.68849999999999989, 0.562000000000000055, 0.370499999999999996, 0.599999999999999978, 15),
-(3312, 'F', 0.479999999999999982, 0.380000000000000004, 0.135000000000000009, 0.507000000000000006, 0.191500000000000004, 0.13650000000000001, 0.154999999999999999, 12),
-(882, 'M', 0.655000000000000027, 0.520000000000000018, 0.165000000000000008, 1.40949999999999998, 0.585999999999999965, 0.290999999999999981, 0.405000000000000027, 9),
-(3402, 'M', 0.479999999999999982, 0.395000000000000018, 0.149999999999999994, 0.681499999999999995, 0.214499999999999996, 0.140500000000000014, 0.2495, 18),
-(829, 'I', 0.409999999999999976, 0.325000000000000011, 0.100000000000000006, 0.394000000000000017, 0.20799999999999999, 0.0655000000000000027, 0.105999999999999997, 6),
-(1305, 'M', 0.535000000000000031, 0.434999999999999998, 0.149999999999999994, 0.716999999999999971, 0.347499999999999976, 0.14449999999999999, 0.194000000000000006, 9),
-(3613, 'M', 0.599999999999999978, 0.46000000000000002, 0.179999999999999993, 1.1399999999999999, 0.422999999999999987, 0.257500000000000007, 0.364999999999999991, 10),
-(1068, 'I', 0.340000000000000024, 0.265000000000000013, 0.0800000000000000017, 0.201500000000000012, 0.0899999999999999967, 0.0475000000000000006, 0.0550000000000000003, 5),
-(2446, 'M', 0.5, 0.380000000000000004, 0.135000000000000009, 0.583500000000000019, 0.22950000000000001, 0.126500000000000001, 0.179999999999999993, 12),
-(1393, 'M', 0.635000000000000009, 0.474999999999999978, 0.170000000000000012, 1.19350000000000001, 0.520499999999999963, 0.269500000000000017, 0.366499999999999992, 10),
-(359, 'M', 0.744999999999999996, 0.584999999999999964, 0.214999999999999997, 2.49900000000000011, 0.92649999999999999, 0.471999999999999975, 0.699999999999999956, 17),
-(549, 'F', 0.564999999999999947, 0.450000000000000011, 0.160000000000000003, 0.79500000000000004, 0.360499999999999987, 0.155499999999999999, 0.23000000000000001, 12),
-(1154, 'F', 0.599999999999999978, 0.474999999999999978, 0.160000000000000003, 1.02649999999999997, 0.484999999999999987, 0.2495, 0.256500000000000006, 9),
-(1790, 'F', 0.54500000000000004, 0.385000000000000009, 0.149999999999999994, 1.11850000000000005, 0.542499999999999982, 0.244499999999999995, 0.284499999999999975, 9),
-(3703, 'F', 0.665000000000000036, 0.540000000000000036, 0.195000000000000007, 1.76400000000000001, 0.850500000000000034, 0.361499999999999988, 0.469999999999999973, 11),
-(1962, 'F', 0.655000000000000027, 0.515000000000000013, 0.179999999999999993, 1.41199999999999992, 0.619500000000000051, 0.248499999999999999, 0.496999999999999997, 11),
-(1665, 'I', 0.604999999999999982, 0.469999999999999973, 0.14499999999999999, 0.802499999999999991, 0.379000000000000004, 0.226500000000000007, 0.220000000000000001, 9),
-(635, 'M', 0.359999999999999987, 0.294999999999999984, 0.100000000000000006, 0.210499999999999993, 0.0660000000000000031, 0.0524999999999999981, 0.0749999999999999972, 9),
-(3901, 'M', 0.445000000000000007, 0.344999999999999973, 0.140000000000000013, 0.475999999999999979, 0.205499999999999988, 0.101500000000000007, 0.108499999999999999, 15),
-(2734, 'I', 0.41499999999999998, 0.33500000000000002, 0.100000000000000006, 0.357999999999999985, 0.169000000000000011, 0.067000000000000004, 0.104999999999999996, 7),
-(3856, 'M', 0.409999999999999976, 0.33500000000000002, 0.115000000000000005, 0.440500000000000003, 0.190000000000000002, 0.0850000000000000061, 0.135000000000000009, 8),
-(827, 'I', 0.395000000000000018, 0.28999999999999998, 0.0950000000000000011, 0.303999999999999992, 0.127000000000000002, 0.0840000000000000052, 0.076999999999999999, 6),
-(3381, 'I', 0.190000000000000002, 0.130000000000000004, 0.0449999999999999983, 0.0264999999999999993, 0.00899999999999999932, 0.0050000000000000001, 0.00899999999999999932, 5),
-(3972, 'I', 0.400000000000000022, 0.294999999999999984, 0.0950000000000000011, 0.252000000000000002, 0.110500000000000001, 0.0575000000000000025, 0.0660000000000000031, 6),
-(1155, 'M', 0.599999999999999978, 0.455000000000000016, 0.170000000000000012, 1.1915, 0.695999999999999952, 0.239499999999999991, 0.239999999999999991, 8),
-(3467, 'M', 0.640000000000000013, 0.5, 0.170000000000000012, 1.4544999999999999, 0.642000000000000015, 0.357499999999999984, 0.353999999999999981, 9),
-(2433, 'F', 0.609999999999999987, 0.484999999999999987, 0.165000000000000008, 1.08699999999999997, 0.425499999999999989, 0.232000000000000012, 0.380000000000000004, 11),
-(552, 'I', 0.614999999999999991, 0.489999999999999991, 0.154999999999999999, 0.988500000000000045, 0.41449999999999998, 0.195000000000000007, 0.344999999999999973, 13),
-(1425, 'F', 0.729999999999999982, 0.57999999999999996, 0.190000000000000002, 1.73750000000000004, 0.678499999999999992, 0.434499999999999997, 0.520000000000000018, 11),
-(2402, 'F', 0.584999999999999964, 0.41499999999999998, 0.154999999999999999, 0.69850000000000001, 0.299999999999999989, 0.145999999999999991, 0.195000000000000007, 12),
-(1748, 'F', 0.699999999999999956, 0.535000000000000031, 0.174999999999999989, 1.77299999999999991, 0.680499999999999994, 0.479999999999999982, 0.512000000000000011, 15),
-(3983, 'I', 0.57999999999999996, 0.434999999999999998, 0.149999999999999994, 0.891499999999999959, 0.362999999999999989, 0.192500000000000004, 0.251500000000000001, 6),
-(335, 'F', 0.739999999999999991, 0.599999999999999978, 0.195000000000000007, 1.97399999999999998, 0.597999999999999976, 0.408499999999999974, 0.709999999999999964, 16),
-(1587, 'I', 0.515000000000000013, 0.349999999999999978, 0.104999999999999996, 0.474499999999999977, 0.212999999999999995, 0.122999999999999998, 0.127500000000000002, 10),
-(2448, 'I', 0.275000000000000022, 0.204999999999999988, 0.0800000000000000017, 0.096000000000000002, 0.0359999999999999973, 0.0184999999999999991, 0.0299999999999999989, 6),
-(1362, 'F', 0.604999999999999982, 0.474999999999999978, 0.174999999999999989, 1.07600000000000007, 0.463000000000000023, 0.219500000000000001, 0.33500000000000002, 9),
-(2799, 'M', 0.640000000000000013, 0.484999999999999987, 0.149999999999999994, 1.09800000000000009, 0.519499999999999962, 0.222000000000000003, 0.317500000000000004, 10),
-(1413, 'F', 0.67000000000000004, 0.505000000000000004, 0.174999999999999989, 1.01449999999999996, 0.4375, 0.271000000000000019, 0.3745, 10),
-(1739, 'F', 0.67000000000000004, 0.540000000000000036, 0.195000000000000007, 1.61899999999999999, 0.739999999999999991, 0.330500000000000016, 0.465000000000000024, 11),
-(1152, 'M', 0.584999999999999964, 0.465000000000000024, 0.160000000000000003, 0.955500000000000016, 0.45950000000000002, 0.235999999999999988, 0.265000000000000013, 7),
-(2427, 'I', 0.564999999999999947, 0.434999999999999998, 0.154999999999999999, 0.782000000000000028, 0.271500000000000019, 0.16800000000000001, 0.284999999999999976, 14),
-(1777, 'M', 0.484999999999999987, 0.369999999999999996, 0.154999999999999999, 0.967999999999999972, 0.418999999999999984, 0.245499999999999996, 0.236499999999999988, 9),
-(3294, 'M', 0.574999999999999956, 0.455000000000000016, 0.184999999999999998, 1.15599999999999992, 0.552499999999999991, 0.242999999999999994, 0.294999999999999984, 13),
-(1403, 'M', 0.650000000000000022, 0.510000000000000009, 0.190000000000000002, 1.54200000000000004, 0.715500000000000025, 0.373499999999999999, 0.375, 9),
-(2256, 'M', 0.510000000000000009, 0.395000000000000018, 0.14499999999999999, 0.61850000000000005, 0.215999999999999998, 0.138500000000000012, 0.239999999999999991, 12),
-(3984, 'F', 0.584999999999999964, 0.450000000000000011, 0.125, 0.873999999999999999, 0.354499999999999982, 0.20749999999999999, 0.225000000000000006, 6),
-(1116, 'M', 0.525000000000000022, 0.405000000000000027, 0.119999999999999996, 0.755499999999999949, 0.3755, 0.155499999999999999, 0.201000000000000012, 9),
-(1366, 'M', 0.609999999999999987, 0.474999999999999978, 0.170000000000000012, 1.02649999999999997, 0.434999999999999998, 0.233500000000000013, 0.303499999999999992, 10),
-(3759, 'I', 0.525000000000000022, 0.400000000000000022, 0.140000000000000013, 0.605500000000000038, 0.260500000000000009, 0.107999999999999999, 0.209999999999999992, 9);
+\i m4_regexp(MADLIB_LIBRARY_PATH,
+ `\(.*\)/lib',
+ `\1/../modules/pmml/test/pmml.setup.sql_in'
+)
+m4_changequote(`<!'', `!>'')
+------------ with intercept ------------------------------------
DROP TABLE IF EXISTS abalone_out, abalone_out_summary;
SELECT glm(
'abalone',
@@ -85,4 +15,48 @@ SELECT glm(
'family=inverse_gaussian, link=sqr_inverse', NULL, 'max_iter=1000, tolerance=1e-16'
);
-SELECT pmml('abalone_out');
+DROP TABLE IF EXISTS glm_predict_inverse_gaussian_out; CREATE TABLE glm_predict_inverse_gaussian_out as SELECT id, glm_predict(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'sqr_inverse')
+FROM abalone_out, abalone;
+SELECT test_pmml_output('abalone', 'abalone_out', 'glm_predict_inverse_gaussian_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
+
+------------ without intercept ------------------------------------
+DROP TABLE IF EXISTS abalone_out_nointercept, abalone_out_nointercept_summary;
+SELECT glm(
+ 'abalone',
+ 'abalone_out_nointercept',
+ 'rings',
+ 'ARRAY[length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=inverse_gaussian, link=inverse',NULL, 'max_iter=1000, tolerance=1e-16'
+);
+
+DROP TABLE IF EXISTS glm_predict_inverse_gaussian_out; CREATE TABLE glm_predict_inverse_gaussian_out as SELECT id, glm_predict(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'inverse')
+FROM abalone_out_nointercept, abalone;
+SELECT test_pmml_output('abalone', 'abalone_out_nointercept', 'glm_predict_inverse_gaussian_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
+
+
+----------- with 0 intercept ---------------------------------------
+DROP TABLE IF EXISTS abalone_out_zerointercept, abalone_out_zerointercept_summary;
+SELECT glm(
+ 'abalone',
+ 'abalone_out_zerointercept',
+ 'rings',
+ 'ARRAY[0, length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=inverse_gaussian, link=inverse', NULL, 'max_iter=1000, tolerance=1e-16'
+);
+
+DROP TABLE IF EXISTS glm_predict_inverse_gaussian_out; CREATE TABLE glm_predict_inverse_gaussian_out as SELECT id, glm_predict(coef, ARRAY[0, length, diameter, height, whole, shucked, viscera, shell], 'inverse')
+FROM abalone_out_zerointercept, abalone;
+SELECT test_pmml_output('abalone', 'abalone_out_zerointercept', 'glm_predict_inverse_gaussian_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
+
+DROP TABLE IF EXISTS abalone_out_zerointercept, abalone_out_zerointercept_summary;
+SELECT glm(
+ 'abalone',
+ 'abalone_out_zerointercept',
+ 'rings',
+ 'ARRAY[0.0, length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=inverse_gaussian, link=inverse', NULL, 'max_iter=1000, tolerance=1e-16'
+);
+
+DROP TABLE IF EXISTS glm_predict_inverse_gaussian_out; CREATE TABLE glm_predict_inverse_gaussian_out as SELECT id, glm_predict(coef, ARRAY[0, length, diameter, height, whole, shucked, viscera, shell], 'inverse')
+FROM abalone_out_zerointercept, abalone;
+SELECT test_pmml_output('abalone', 'abalone_out_zerointercept', 'glm_predict_inverse_gaussian_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
diff --git a/src/ports/postgres/modules/pmml/test/pmml_glm_normal.sql_in b/src/ports/postgres/modules/pmml/test/pmml_glm_normal.sql_in
index 6c80595c..7616c644 100644
--- a/src/ports/postgres/modules/pmml/test/pmml_glm_normal.sql_in
+++ b/src/ports/postgres/modules/pmml/test/pmml_glm_normal.sql_in
@@ -1,88 +1,101 @@
-DROP TABLE IF EXISTS abalone;
-
-CREATE TABLE abalone (
- id integer,
- sex text,
- length double precision,
- diameter double precision,
- height double precision,
- whole double precision,
- shucked double precision,
- viscera double precision,
- shell double precision,
- rings integer
+\i m4_regexp(MADLIB_LIBRARY_PATH,
+ `\(.*\)/lib',
+ `\1/../modules/pmml/test/pmml.setup.sql_in'
+)
+
+m4_changequote(`<!'', `!>'')
+
+DROP TABLE IF EXISTS abalone_identity_out, abalone_identity_out_summary;
+SELECT glm(
+ 'abalone',
+ 'abalone_identity_out',
+ 'rings',
+ 'ARRAY[1.0, length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=gaussian, link=identity', NULL, 'max_iter=1000, tolerance=1e-16'
);
-INSERT INTO abalone VALUES
-(3151, 'F', 0.655000000000000027, 0.505000000000000004, 0.165000000000000008, 1.36699999999999999, 0.583500000000000019, 0.351499999999999979, 0.396000000000000019, 10),
-(2026, 'F', 0.550000000000000044, 0.469999999999999973, 0.149999999999999994, 0.920499999999999985, 0.381000000000000005, 0.243499999999999994, 0.267500000000000016, 10),
-(3751, 'I', 0.434999999999999998, 0.375, 0.110000000000000001, 0.41549999999999998, 0.170000000000000012, 0.0759999999999999981, 0.14499999999999999, 8),
-(720, 'I', 0.149999999999999994, 0.100000000000000006, 0.0250000000000000014, 0.0149999999999999994, 0.00449999999999999966, 0.00400000000000000008, 0.0050000000000000001, 2),
-(1635, 'F', 0.574999999999999956, 0.469999999999999973, 0.154999999999999999, 1.1160000000000001, 0.509000000000000008, 0.237999999999999989, 0.340000000000000024, 10),
-(2648, 'I', 0.5, 0.390000000000000013, 0.125, 0.582999999999999963, 0.293999999999999984, 0.132000000000000006, 0.160500000000000004, 8),
-(1796, 'F', 0.57999999999999996, 0.429999999999999993, 0.170000000000000012, 1.47999999999999998, 0.65349999999999997, 0.32400000000000001, 0.41549999999999998, 10),
-(209, 'F', 0.525000000000000022, 0.41499999999999998, 0.170000000000000012, 0.832500000000000018, 0.275500000000000023, 0.168500000000000011, 0.309999999999999998, 13),
-(1451, 'I', 0.455000000000000016, 0.33500000000000002, 0.135000000000000009, 0.501000000000000001, 0.274000000000000021, 0.0995000000000000051, 0.106499999999999997, 7),
-(1108, 'I', 0.510000000000000009, 0.380000000000000004, 0.115000000000000005, 0.515499999999999958, 0.214999999999999997, 0.113500000000000004, 0.166000000000000009, 8),
-(3675, 'F', 0.594999999999999973, 0.450000000000000011, 0.165000000000000008, 1.08099999999999996, 0.489999999999999991, 0.252500000000000002, 0.279000000000000026, 12),
-(2108, 'F', 0.675000000000000044, 0.550000000000000044, 0.179999999999999993, 1.68849999999999989, 0.562000000000000055, 0.370499999999999996, 0.599999999999999978, 15),
-(3312, 'F', 0.479999999999999982, 0.380000000000000004, 0.135000000000000009, 0.507000000000000006, 0.191500000000000004, 0.13650000000000001, 0.154999999999999999, 12),
-(882, 'M', 0.655000000000000027, 0.520000000000000018, 0.165000000000000008, 1.40949999999999998, 0.585999999999999965, 0.290999999999999981, 0.405000000000000027, 9),
-(3402, 'M', 0.479999999999999982, 0.395000000000000018, 0.149999999999999994, 0.681499999999999995, 0.214499999999999996, 0.140500000000000014, 0.2495, 18),
-(829, 'I', 0.409999999999999976, 0.325000000000000011, 0.100000000000000006, 0.394000000000000017, 0.20799999999999999, 0.0655000000000000027, 0.105999999999999997, 6),
-(1305, 'M', 0.535000000000000031, 0.434999999999999998, 0.149999999999999994, 0.716999999999999971, 0.347499999999999976, 0.14449999999999999, 0.194000000000000006, 9),
-(3613, 'M', 0.599999999999999978, 0.46000000000000002, 0.179999999999999993, 1.1399999999999999, 0.422999999999999987, 0.257500000000000007, 0.364999999999999991, 10),
-(1068, 'I', 0.340000000000000024, 0.265000000000000013, 0.0800000000000000017, 0.201500000000000012, 0.0899999999999999967, 0.0475000000000000006, 0.0550000000000000003, 5),
-(2446, 'M', 0.5, 0.380000000000000004, 0.135000000000000009, 0.583500000000000019, 0.22950000000000001, 0.126500000000000001, 0.179999999999999993, 12),
-(1393, 'M', 0.635000000000000009, 0.474999999999999978, 0.170000000000000012, 1.19350000000000001, 0.520499999999999963, 0.269500000000000017, 0.366499999999999992, 10),
-(359, 'M', 0.744999999999999996, 0.584999999999999964, 0.214999999999999997, 2.49900000000000011, 0.92649999999999999, 0.471999999999999975, 0.699999999999999956, 17),
-(549, 'F', 0.564999999999999947, 0.450000000000000011, 0.160000000000000003, 0.79500000000000004, 0.360499999999999987, 0.155499999999999999, 0.23000000000000001, 12),
-(1154, 'F', 0.599999999999999978, 0.474999999999999978, 0.160000000000000003, 1.02649999999999997, 0.484999999999999987, 0.2495, 0.256500000000000006, 9),
-(1790, 'F', 0.54500000000000004, 0.385000000000000009, 0.149999999999999994, 1.11850000000000005, 0.542499999999999982, 0.244499999999999995, 0.284499999999999975, 9),
-(3703, 'F', 0.665000000000000036, 0.540000000000000036, 0.195000000000000007, 1.76400000000000001, 0.850500000000000034, 0.361499999999999988, 0.469999999999999973, 11),
-(1962, 'F', 0.655000000000000027, 0.515000000000000013, 0.179999999999999993, 1.41199999999999992, 0.619500000000000051, 0.248499999999999999, 0.496999999999999997, 11),
-(1665, 'I', 0.604999999999999982, 0.469999999999999973, 0.14499999999999999, 0.802499999999999991, 0.379000000000000004, 0.226500000000000007, 0.220000000000000001, 9),
-(635, 'M', 0.359999999999999987, 0.294999999999999984, 0.100000000000000006, 0.210499999999999993, 0.0660000000000000031, 0.0524999999999999981, 0.0749999999999999972, 9),
-(3901, 'M', 0.445000000000000007, 0.344999999999999973, 0.140000000000000013, 0.475999999999999979, 0.205499999999999988, 0.101500000000000007, 0.108499999999999999, 15),
-(2734, 'I', 0.41499999999999998, 0.33500000000000002, 0.100000000000000006, 0.357999999999999985, 0.169000000000000011, 0.067000000000000004, 0.104999999999999996, 7),
-(3856, 'M', 0.409999999999999976, 0.33500000000000002, 0.115000000000000005, 0.440500000000000003, 0.190000000000000002, 0.0850000000000000061, 0.135000000000000009, 8),
-(827, 'I', 0.395000000000000018, 0.28999999999999998, 0.0950000000000000011, 0.303999999999999992, 0.127000000000000002, 0.0840000000000000052, 0.076999999999999999, 6),
-(3381, 'I', 0.190000000000000002, 0.130000000000000004, 0.0449999999999999983, 0.0264999999999999993, 0.00899999999999999932, 0.0050000000000000001, 0.00899999999999999932, 5),
-(3972, 'I', 0.400000000000000022, 0.294999999999999984, 0.0950000000000000011, 0.252000000000000002, 0.110500000000000001, 0.0575000000000000025, 0.0660000000000000031, 6),
-(1155, 'M', 0.599999999999999978, 0.455000000000000016, 0.170000000000000012, 1.1915, 0.695999999999999952, 0.239499999999999991, 0.239999999999999991, 8),
-(3467, 'M', 0.640000000000000013, 0.5, 0.170000000000000012, 1.4544999999999999, 0.642000000000000015, 0.357499999999999984, 0.353999999999999981, 9),
-(2433, 'F', 0.609999999999999987, 0.484999999999999987, 0.165000000000000008, 1.08699999999999997, 0.425499999999999989, 0.232000000000000012, 0.380000000000000004, 11),
-(552, 'I', 0.614999999999999991, 0.489999999999999991, 0.154999999999999999, 0.988500000000000045, 0.41449999999999998, 0.195000000000000007, 0.344999999999999973, 13),
-(1425, 'F', 0.729999999999999982, 0.57999999999999996, 0.190000000000000002, 1.73750000000000004, 0.678499999999999992, 0.434499999999999997, 0.520000000000000018, 11),
-(2402, 'F', 0.584999999999999964, 0.41499999999999998, 0.154999999999999999, 0.69850000000000001, 0.299999999999999989, 0.145999999999999991, 0.195000000000000007, 12),
-(1748, 'F', 0.699999999999999956, 0.535000000000000031, 0.174999999999999989, 1.77299999999999991, 0.680499999999999994, 0.479999999999999982, 0.512000000000000011, 15),
-(3983, 'I', 0.57999999999999996, 0.434999999999999998, 0.149999999999999994, 0.891499999999999959, 0.362999999999999989, 0.192500000000000004, 0.251500000000000001, 6),
-(335, 'F', 0.739999999999999991, 0.599999999999999978, 0.195000000000000007, 1.97399999999999998, 0.597999999999999976, 0.408499999999999974, 0.709999999999999964, 16),
-(1587, 'I', 0.515000000000000013, 0.349999999999999978, 0.104999999999999996, 0.474499999999999977, 0.212999999999999995, 0.122999999999999998, 0.127500000000000002, 10),
-(2448, 'I', 0.275000000000000022, 0.204999999999999988, 0.0800000000000000017, 0.096000000000000002, 0.0359999999999999973, 0.0184999999999999991, 0.0299999999999999989, 6),
-(1362, 'F', 0.604999999999999982, 0.474999999999999978, 0.174999999999999989, 1.07600000000000007, 0.463000000000000023, 0.219500000000000001, 0.33500000000000002, 9),
-(2799, 'M', 0.640000000000000013, 0.484999999999999987, 0.149999999999999994, 1.09800000000000009, 0.519499999999999962, 0.222000000000000003, 0.317500000000000004, 10),
-(1413, 'F', 0.67000000000000004, 0.505000000000000004, 0.174999999999999989, 1.01449999999999996, 0.4375, 0.271000000000000019, 0.3745, 10),
-(1739, 'F', 0.67000000000000004, 0.540000000000000036, 0.195000000000000007, 1.61899999999999999, 0.739999999999999991, 0.330500000000000016, 0.465000000000000024, 11),
-(1152, 'M', 0.584999999999999964, 0.465000000000000024, 0.160000000000000003, 0.955500000000000016, 0.45950000000000002, 0.235999999999999988, 0.265000000000000013, 7),
-(2427, 'I', 0.564999999999999947, 0.434999999999999998, 0.154999999999999999, 0.782000000000000028, 0.271500000000000019, 0.16800000000000001, 0.284999999999999976, 14),
-(1777, 'M', 0.484999999999999987, 0.369999999999999996, 0.154999999999999999, 0.967999999999999972, 0.418999999999999984, 0.245499999999999996, 0.236499999999999988, 9),
-(3294, 'M', 0.574999999999999956, 0.455000000000000016, 0.184999999999999998, 1.15599999999999992, 0.552499999999999991, 0.242999999999999994, 0.294999999999999984, 13),
-(1403, 'M', 0.650000000000000022, 0.510000000000000009, 0.190000000000000002, 1.54200000000000004, 0.715500000000000025, 0.373499999999999999, 0.375, 9),
-(2256, 'M', 0.510000000000000009, 0.395000000000000018, 0.14499999999999999, 0.61850000000000005, 0.215999999999999998, 0.138500000000000012, 0.239999999999999991, 12),
-(3984, 'F', 0.584999999999999964, 0.450000000000000011, 0.125, 0.873999999999999999, 0.354499999999999982, 0.20749999999999999, 0.225000000000000006, 6),
-(1116, 'M', 0.525000000000000022, 0.405000000000000027, 0.119999999999999996, 0.755499999999999949, 0.3755, 0.155499999999999999, 0.201000000000000012, 9),
-(1366, 'M', 0.609999999999999987, 0.474999999999999978, 0.170000000000000012, 1.02649999999999997, 0.434999999999999998, 0.233500000000000013, 0.303499999999999992, 10),
-(3759, 'I', 0.525000000000000022, 0.400000000000000022, 0.140000000000000013, 0.605500000000000038, 0.260500000000000009, 0.107999999999999999, 0.209999999999999992, 9);
-
-
-DROP TABLE IF EXISTS abalone_out, abalone_out_summary;
+DROP TABLE IF EXISTS glm_predict_normal_out; CREATE TABLE glm_predict_normal_out as SELECT id, glm_predict(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'identity')
+FROM abalone_identity_out, abalone;
+SELECT test_pmml_output('abalone', 'abalone_identity_out', 'glm_predict_normal_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
+
+DROP TABLE IF EXISTS abalone_log_out, abalone_log_out_summary;
SELECT glm(
'abalone',
- 'abalone_out',
+ 'abalone_log_out',
'rings',
'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=gaussian, link=log', NULL, 'max_iter=1000, tolerance=1e-16'
+);
+
+DROP TABLE IF EXISTS glm_predict_normal_out; CREATE TABLE glm_predict_normal_out as SELECT id, glm_predict(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'log')
+FROM abalone_log_out, abalone;
+SELECT test_pmml_output('abalone', 'abalone_log_out', 'glm_predict_normal_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
+
+DROP TABLE IF EXISTS abalone_inverse_out, abalone_inverse_out_summary;
+SELECT glm(
+ 'abalone',
+ 'abalone_inverse_out',
+ 'rings',
+ 'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=gaussian, link=inverse', NULL, 'max_iter=1000, tolerance=1e-16'
+);
+
+DROP TABLE IF EXISTS glm_predict_normal_out; CREATE TABLE glm_predict_normal_out as SELECT id, glm_predict(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'inverse')
+FROM abalone_inverse_out, abalone;
+SELECT test_pmml_output('abalone', 'abalone_inverse_out', 'glm_predict_normal_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
+
+
+------------------------ without intercept ------------------------------------------------------------
+DROP TABLE IF EXISTS abalone_identity_out_nointercept, abalone_identity_out_nointercept_summary;
+SELECT glm(
+ 'abalone',
+ 'abalone_identity_out_nointercept',
+ 'rings',
+ 'ARRAY[length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=gaussian, link=identity', NULL, 'max_iter=1000, tolerance=1e-16'
+);
+
+DROP TABLE IF EXISTS glm_predict_normal_out; CREATE TABLE glm_predict_normal_out as SELECT id, glm_predict(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'identity')
+FROM abalone_identity_out_nointercept, abalone;
+SELECT test_pmml_output('abalone', 'abalone_identity_out_nointercept', 'glm_predict_normal_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
+
+DROP TABLE IF EXISTS abalone_log_out_nointercept, abalone_log_out_nointercept_summary;
+SELECT glm(
+ 'abalone',
+ 'abalone_log_out_nointercept',
+ 'rings',
+ 'ARRAY[length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=gaussian, link=log', NULL, 'max_iter=1000, tolerance=1e-16'
+);
+
+DROP TABLE IF EXISTS glm_predict_normal_out; CREATE TABLE glm_predict_normal_out as SELECT id, glm_predict(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'log')
+FROM abalone_log_out_nointercept, abalone;
+SELECT test_pmml_output('abalone', 'abalone_log_out_nointercept', 'glm_predict_normal_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
+
+DROP TABLE IF EXISTS abalone_inverse_out_nointercept, abalone_inverse_out_nointercept_summary;
+SELECT glm(
+ 'abalone',
+ 'abalone_inverse_out_nointercept',
+ 'rings',
+ 'ARRAY[length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=gaussian, link=inverse', NULL, 'max_iter=1000, tolerance=1e-16'
+);
+
+DROP TABLE IF EXISTS glm_predict_normal_out; CREATE TABLE glm_predict_normal_out as SELECT id, glm_predict(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'inverse')
+FROM abalone_inverse_out_nointercept, abalone;
+SELECT test_pmml_output('abalone', 'abalone_inverse_out_nointercept', 'glm_predict_normal_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
+
+
+------------------------ with 0 intercept ------------------------------------------------------------
+DROP TABLE IF EXISTS abalone_identity_out_zerointercept, abalone_identity_out_zerointercept_summary;
+SELECT glm(
+ 'abalone',
+ 'abalone_identity_out_zerointercept',
+ 'rings',
+ 'ARRAY[0, length, diameter, height, whole, shucked, viscera, shell]',
'family=gaussian, link=identity', NULL, 'max_iter=1000, tolerance=1e-16'
);
-SELECT pmml('abalone_out');
+DROP TABLE IF EXISTS glm_predict_normal_out; CREATE TABLE glm_predict_normal_out as SELECT id, glm_predict(coef, ARRAY[0, length, diameter, height, whole, shucked, viscera, shell], 'identity')
+FROM abalone_identity_out_zerointercept, abalone;
+SELECT test_pmml_output('abalone', 'abalone_identity_out_zerointercept', 'glm_predict_normal_out', 'id', 'glm_predict', 'predicted_rings_pmml_prediction');
diff --git a/src/ports/postgres/modules/pmml/test/pmml_glm_poisson.sql_in b/src/ports/postgres/modules/pmml/test/pmml_glm_poisson.sql_in
index fe581352..2dcae6d6 100644
--- a/src/ports/postgres/modules/pmml/test/pmml_glm_poisson.sql_in
+++ b/src/ports/postgres/modules/pmml/test/pmml_glm_poisson.sql_in
@@ -1,77 +1,59 @@
-DROP TABLE IF EXISTS warpbreaks CASCADE;
-
-CREATE TABLE warpbreaks(
- id serial,
- breaks integer,
- wool char(1),
- tension char(1),
- g char(1)
-);
+\i m4_regexp(MADLIB_LIBRARY_PATH,
+ `\(.*\)/lib',
+ `\1/../modules/pmml/test/pmml.setup.sql_in'
+)
-INSERT INTO warpbreaks(breaks, wool, tension, g) VALUES
-(26, 'A', 'L', '1'),
-(30, 'A', 'L', '1'),
-(54, 'A', 'L', '1'),
-(25, 'A', 'L', '1'),
-(70, 'A', 'L', '1'),
-(52, 'A', 'L', '1'),
-(51, 'A', 'L', '1'),
-(26, 'A', 'L', '1'),
-(67, 'A', 'L', '1'),
-(18, 'A', 'M', '1'),
-(21, 'A', 'M', '1'),
-(29, 'A', 'M', '1'),
-(17, 'A', 'M', '1'),
-(12, 'A', 'M', '1'),
-(18, 'A', 'M', '1'),
-(35, 'A', 'M', '1'),
-(30, 'A', 'M', '1'),
-(36, 'A', 'M', '1'),
-(36, 'A', 'H', '0'),
-(21, 'A', 'H', '0'),
-(24, 'A', 'H', '0'),
-(18, 'A', 'H', '0'),
-(10, 'A', 'H', '0'),
-(43, 'A', 'H', '0'),
-(28, 'A', 'H', '0'),
-(15, 'A', 'H', '0'),
-(26, 'A', 'H', '0'),
-(27, 'B', 'L', '0'),
-(14, 'B', 'L', '0'),
-(29, 'B', 'L', '0'),
-(19, 'B', 'L', '0'),
-(29, 'B', 'L', '0'),
-(31, 'B', 'L', '0'),
-(41, 'B', 'L', '0'),
-(20, 'B', 'L', '1'),
-(44, 'B', 'L', '1'),
-(42, 'B', 'M', '1'),
-(26, 'B', 'M', '1'),
-(19, 'B', 'M', '1'),
-(16, 'B', 'M', '1'),
-(39, 'B', 'M', '1'),
-(28, 'B', 'M', '1'),
-(21, 'B', 'M', '1'),
-(39, 'B', 'M', '1'),
-(29, 'B', 'M', '1'),
-(20, 'B', 'H', '1'),
-(21, 'B', 'H', '1'),
-(24, 'B', 'H', '1'),
-(17, 'B', 'H', '1'),
-(13, 'B', 'H', '1'),
-(15, 'B', 'H', '1'),
-(15, 'B', 'H', '1'),
-(16, 'B', 'H', '1'),
-(28, 'B', 'H', '1');
+m4_changequote(`<!'', `!>'')
-DROP TABLE IF EXISTS warpbreaks_dummy;
-SELECT create_indicator_variables('warpbreaks', 'warpbreaks_dummy', 'wool,tension');
+DROP TABLE IF EXISTS warpbreaks CASCADE;
+-------------------- with intercept ------------------------------
DROP TABLE IF EXISTS glm_model_sqrt, glm_model_sqrt_summary;
SELECT glm('warpbreaks_dummy',
'glm_model_sqrt',
'breaks',
- 'ARRAY[1.0,"wool_B","tension_M", "tension_H"]',
+ 'ARRAY[1.0, "wool_B","tension_M", "tension_H"]',
'family=poisson, link=sqrt');
-SELECT pmml('glm_model_sqrt');
+-- Test predicted value
+DROP TABLE IF EXISTS glm_predict_poisson_sqrt_out; CREATE TABLE glm_predict_poisson_sqrt_out as SELECT id, glm_predict(coef, ARRAY[1, "wool_B","tension_M", "tension_H"], 'sqrt')
+FROM glm_model_sqrt, warpbreaks_dummy;
+SELECT test_pmml_output('warpbreaks_dummy', 'glm_model_sqrt', 'glm_predict_poisson_sqrt_out', 'id', 'glm_predict', 'predicted_breaks_pmml_prediction');
+
+DROP TABLE IF EXISTS glm_model_log, glm_model_log_summary;
+SELECT glm('warpbreaks_dummy',
+ 'glm_model_log',
+ 'breaks',
+ 'ARRAY[1, "wool_B","tension_M", "tension_H"]',
+ 'family=poisson, link=log');
+
+-- Test predicted value
+DROP TABLE IF EXISTS glm_predict_poisson_log_out; CREATE TABLE glm_predict_poisson_log_out as SELECT id, glm_predict(coef, ARRAY[1, "wool_B","tension_M", "tension_H"], 'log')
+FROM glm_model_log, warpbreaks_dummy;
+SELECT test_pmml_output('warpbreaks_dummy', 'glm_model_log', 'glm_predict_poisson_log_out', 'id', 'glm_predict', 'predicted_breaks_pmml_prediction');
+
+DROP TABLE IF EXISTS glm_model_identity, glm_model_identity_summary;
+SELECT glm('warpbreaks_dummy',
+ 'glm_model_identity',
+ 'breaks',
+ 'ARRAY[1.0, "wool_B","tension_M", "tension_H"]',
+ 'family=poisson, link=identity', 'g');
+
+-- Test predicted value
+DROP TABLE IF EXISTS glm_predict_poisson_identity_out; CREATE TABLE glm_predict_poisson_identity_out as SELECT id, glm_model_identity.g, glm_predict(coef, ARRAY[1, "wool_B","tension_M", "tension_H"], 'identity')
+FROM glm_model_identity, warpbreaks_dummy;
+SELECT test_pmml_output('warpbreaks_dummy', 'glm_model_identity', 'glm_predict_poisson_identity_out', 'id', 'glm_predict', 'predicted_breaks_pmml_prediction', 'g');
+
+-------------------- without intercept ------------------------------
+-- TODO: create item for fixing the glm module when link='sqrt'/'identity' and no intercept is used
+DROP TABLE IF EXISTS glm_model_log_nointercept, glm_model_log_nointercept_summary;
+SELECT glm('warpbreaks_dummy',
+ 'glm_model_log_nointercept',
+ 'breaks',
+ 'ARRAY["wool_B","tension_M", "tension_H"]',
+ 'family=poisson, link=log');
+
+-- Test predicted value
+DROP TABLE IF EXISTS glm_predict_poisson_log_out; CREATE TABLE glm_predict_poisson_log_out as SELECT id, glm_predict(coef, ARRAY["wool_B","tension_M", "tension_H"], 'log')
+FROM glm_model_log_nointercept, warpbreaks_dummy;
+SELECT test_pmml_output('warpbreaks_dummy', 'glm_model_log_nointercept', 'glm_predict_poisson_log_out', 'id', 'glm_predict', 'predicted_breaks_pmml_prediction');
diff --git a/src/ports/postgres/modules/pmml/test/pmml_glm_with_grouping.sql_in b/src/ports/postgres/modules/pmml/test/pmml_glm_with_grouping.sql_in
new file mode 100644
index 00000000..b3852ecd
--- /dev/null
+++ b/src/ports/postgres/modules/pmml/test/pmml_glm_with_grouping.sql_in
@@ -0,0 +1,125 @@
+/* ----------------------------------------------------------------------- *//**
+ *
+ * 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.
+ *
+ *//* ----------------------------------------------------------------------- */
+
+\i m4_regexp(MADLIB_LIBRARY_PATH,
+ `\(.*\)/lib',
+ `\1/../modules/pmml/test/pmml.setup.sql_in'
+)
+
+m4_changequote(`<!'', `!>'')
+--TODO: Should all the predict and model tables have the same name ?
+
+----------------------- binomial with logit -------------------------------
+DROP TABLE IF EXISTS glm_model, glm_model_summary;
+SELECT glm(
+ 'abalone',
+ 'glm_model',
+ 'rings < 10',
+ 'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=binomial, link=logit', 'sex,id', 'max_iter=1000, tolerance=1e-16'
+);
+
+-- Test probabilities
+DROP TABLE IF EXISTS glm_predict_output; CREATE TABLE glm_predict_output as SELECT glm_model.id, glm_model.sex, glm_predict(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'logit')
+FROM glm_model, abalone WHERE abalone.id=glm_model.id and abalone.sex=glm_model.sex;
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_output', 'id', 'glm_predict', 'probability_true', 'sex,id');
+
+-- Test output category
+DROP TABLE IF EXISTS glm_predict_output; CREATE TABLE glm_predict_output as SELECT glm_model.id, glm_model.sex, glm_predict_binomial(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'logit')
+FROM glm_model, abalone WHERE abalone.id=glm_model.id and abalone.sex=glm_model.sex;
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_output', 'id', 'glm_predict_binomial', 'predicted_(rings < 10)_pmml_prediction', 'sex,id');
+
+----------------------- binomial with probit without intercept-------------------------------
+DROP TABLE IF EXISTS glm_model, glm_model_summary;
+SELECT glm(
+ 'abalone',
+ 'glm_model',
+ 'rings < 10',
+ 'ARRAY[length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=binomial, link=probit', 'sex', 'max_iter=1000, tolerance=1e-16'
+);
+
+-- Test probabilities
+DROP TABLE IF EXISTS glm_predict_output; CREATE TABLE glm_predict_output as SELECT id, glm_model.sex, glm_predict(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'probit')
+FROM glm_model, abalone WHERE abalone.sex=glm_model.sex;
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_output', 'id', 'glm_predict', 'probability_true', 'sex');
+
+-- Test output category
+DROP TABLE IF EXISTS glm_predict_output; CREATE TABLE glm_predict_output as SELECT id, glm_model.sex, glm_predict_binomial(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'probit')
+FROM glm_model, abalone WHERE abalone.sex=glm_model.sex;
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_output', 'id', 'glm_predict_binomial', 'predicted_(rings < 10)_pmml_prediction', 'sex');
+
+----------------------- gamma with log -------------------------------
+DROP TABLE IF EXISTS glm_model, glm_model_summary;
+SELECT glm(
+ 'abalone',
+ 'glm_model',
+ 'rings',
+ 'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=gamma, link=log', 'sex', 'max_iter=1000, tolerance=1e-16'
+);
+
+DROP TABLE IF EXISTS glm_predict_output; CREATE TABLE glm_predict_output as SELECT id, glm_model.sex, glm_predict(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'log')
+FROM glm_model, abalone WHERE abalone.sex=glm_model.sex;
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_output', 'id', 'glm_predict', 'predicted_rings_pmml_prediction', 'sex');
+--
+-- ----------------------- gamma with log without intercept-------------------------------
+--
+DROP TABLE IF EXISTS glm_model, glm_model_summary;
+SELECT glm(
+ 'abalone',
+ 'glm_model',
+ 'rings',
+ 'ARRAY[length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=gamma, link=log', 'sex', 'max_iter=1000, tolerance=1e-16'
+);
+
+DROP TABLE IF EXISTS glm_predict_output; CREATE TABLE glm_predict_output as SELECT id, glm_model.sex, glm_predict(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'log')
+FROM glm_model, abalone WHERE abalone.sex=glm_model.sex;
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_output', 'id', 'glm_predict', 'predicted_rings_pmml_prediction', 'sex');
+
+
+------------ inverse_gaussian with inverse without intercept ------------------------------------
+DROP TABLE IF EXISTS glm_model, glm_model_summary;
+SELECT glm(
+ 'abalone',
+ 'glm_model',
+ 'rings',
+ 'ARRAY[length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=inverse_gaussian, link=inverse', 'sex,id', 'max_iter=1000, tolerance=1e-16'
+);
+
+DROP TABLE IF EXISTS glm_predict_output; CREATE TABLE glm_predict_output as SELECT glm_model.id, glm_model.sex, glm_predict(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'inverse')
+FROM glm_model, abalone WHERE abalone.sex=glm_model.sex and abalone.id=glm_model.id;
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_output', 'id', 'glm_predict', 'predicted_rings_pmml_prediction', 'sex,id');
+
+------------ poisson with identity with intercept ------------------------------------
+DROP TABLE IF EXISTS glm_model, glm_model_summary;
+SELECT glm('warpbreaks_dummy',
+ 'glm_model',
+ 'breaks',
+ 'ARRAY[1, "wool_B","tension_M", "tension_H"]',
+ 'family=poisson, link=identity', 'g');
+
+-- Test predicted value
+DROP TABLE IF EXISTS glm_predict_output; CREATE TABLE glm_predict_output as SELECT id, glm_model.g, glm_predict(coef, ARRAY[1, "wool_B","tension_M", "tension_H"], 'identity')
+FROM glm_model, warpbreaks_dummy WHERE warpbreaks_dummy.g=glm_model.g;
+SELECT test_pmml_output('warpbreaks_dummy', 'glm_model', 'glm_predict_output', 'id', 'glm_predict', 'predicted_breaks_pmml_prediction', 'g');
diff --git a/src/ports/postgres/modules/pmml/test/pmml_glm_with_name_spec.sql_in b/src/ports/postgres/modules/pmml/test/pmml_glm_with_name_spec.sql_in
new file mode 100644
index 00000000..472bc3a1
--- /dev/null
+++ b/src/ports/postgres/modules/pmml/test/pmml_glm_with_name_spec.sql_in
@@ -0,0 +1,160 @@
+/* ----------------------------------------------------------------------- *//**
+ *
+ * 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.
+ *
+ *//* ----------------------------------------------------------------------- */
+
+ \i m4_regexp(MADLIB_LIBRARY_PATH,
+ `\(.*\)/lib',
+ `\1/../modules/pmml/test/pmml.setup.sql_in'
+)
+
+m4_changequote(`<!'', `!>'')
+
+CREATE TABLE abalone_test_for_pmml as SELECT *, length as foo1, diameter as foo2, height as foo3, whole as foo4, shucked as foo5, viscera as foo6, shell as foo7 FROM abalone;
+
+----------------------- with intercept -------------------------------
+DROP TABLE IF EXISTS glm_model, glm_model_summary;
+SELECT glm(
+ 'abalone',
+ 'glm_model',
+ 'rings < 10',
+ 'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=binomial, link=logit', NULL, 'max_iter=1000, tolerance=1e-16'
+);
+
+-- -- Test probabilities
+DROP TABLE IF EXISTS glm_predict_binomial_logit_out; CREATE TABLE glm_predict_binomial_logit_out as SELECT id, glm_predict(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'logit')
+FROM glm_model, abalone;
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', '','bar ~ foo1+foo2+foo3+foo4+foo5+foo6+foo7');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', '','foo1+foo2+foo3+foo4+foo5+foo6+foo7');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', '','{bar,foo1,foo2,foo3,foo4,foo5,foo6,foo7}');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', '','{foo1,foo2,foo3,foo4,foo5,foo6,foo7}');
+
+-- Test output category
+DROP TABLE IF EXISTS glm_predict_binomial_logit_out; CREATE TABLE glm_predict_binomial_logit_out as SELECT id, glm_predict_binomial(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'logit')
+FROM glm_model, abalone;
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_bar', '', 'bar ~ foo1+foo2+foo3+foo4+foo5+foo6+foo7');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_rings < 10', '', 'foo1+foo2+foo3+foo4+foo5+foo6+foo7');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_bar', '', '{bar,foo1,foo2,foo3,foo4,foo5,foo6,foo7}');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_rings < 10', '', '{foo1,foo2,foo3,foo4,foo5,foo6,foo7}');
+
+----------------------- without intercept -------------------------------
+DROP TABLE IF EXISTS glm_model, glm_model_summary;
+SELECT glm(
+ 'abalone',
+ 'glm_model',
+ 'rings < 10',
+ 'ARRAY[length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=binomial, link=logit', NULL, 'max_iter=1000, tolerance=1e-16'
+);
+
+-- -- Test probabilities
+DROP TABLE IF EXISTS glm_predict_binomial_logit_out; CREATE TABLE glm_predict_binomial_logit_out as SELECT id, glm_predict(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'logit')
+FROM glm_model, abalone;
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', '','bar ~ foo1+foo2+foo3+foo4+foo5+foo6+foo7');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', '','foo1+foo2+foo3+foo4+foo5+foo6+foo7');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', '','{bar, foo1,foo2,foo3,foo4,foo5,foo6,foo7}');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', '','{foo1,foo2,foo3,foo4,foo5,foo6,foo7}');
+
+-- Test output category
+DROP TABLE IF EXISTS glm_predict_binomial_logit_out; CREATE TABLE glm_predict_binomial_logit_out as SELECT id, glm_predict_binomial(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'logit')
+FROM glm_model, abalone;
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_bar', '', 'bar ~ foo1+foo2+foo3+foo4+foo5+foo6+foo7');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_rings < 10', '', 'foo1+foo2+foo3+foo4+foo5+foo6+foo7');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_bar', '', '{bar, foo1,foo2,foo3,foo4,foo5,foo6,foo7}');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_rings < 10', '', '{foo1,foo2,foo3,foo4,foo5,foo6,foo7}');
+
+
+---------------------------- with grouping -----------------------------------------
+DROP TABLE IF EXISTS glm_model, glm_model_summary;
+SELECT glm(
+ 'abalone',
+ 'glm_model',
+ 'rings < 10',
+ 'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=binomial, link=logit', 'sex', 'max_iter=1000, tolerance=1e-16'
+);
+
+-- -- Test probabilities
+DROP TABLE IF EXISTS glm_predict_binomial_logit_out; CREATE TABLE glm_predict_binomial_logit_out as SELECT id, glm_model.sex, glm_predict(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'logit')
+FROM glm_model, abalone WHERE abalone.sex=glm_model.sex;
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', 'sex','bar ~ foo1+foo2+foo3+foo4+foo5+foo6+foo7');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', 'sex','foo1+foo2+foo3+foo4+foo5+foo6+foo7');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', 'sex','{bar, foo1,foo2,foo3,foo4,foo5,foo6,foo7}');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', 'sex','{foo1,foo2,foo3,foo4,foo5,foo6,foo7}');
+
+-- Test output category
+DROP TABLE IF EXISTS glm_predict_binomial_logit_out; CREATE TABLE glm_predict_binomial_logit_out as SELECT id, glm_model.sex, glm_predict_binomial(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'logit')
+FROM glm_model, abalone WHERE abalone.sex=glm_model.sex;
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_bar', 'sex', 'bar ~ foo1+foo2+foo3+foo4+foo5+foo6+foo7');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_rings < 10', 'sex', 'foo1+foo2+foo3+foo4+foo5+foo6+foo7');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_bar', 'sex', '{bar, foo1,foo2,foo3,foo4,foo5,foo6,foo7}');
+SELECT test_pmml_output('abalone_test_for_pmml', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_rings < 10', 'sex', '{foo1,foo2,foo3,foo4,foo5,foo6,foo7}');
+
+
+----------------------- with grouping and incorrect feature length in name spec -------------------------
+-- Incorrect count type1: If the count of features in the name spec is incorrect, madlib pmml will fall back to using the original names
+-- So we can use the original table 'abalone' to compare the results
+
+DROP TABLE IF EXISTS glm_model, glm_model_summary;
+SELECT glm(
+ 'abalone',
+ 'glm_model',
+ 'rings < 10',
+ 'ARRAY[1, length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=binomial, link=logit', 'sex', 'max_iter=1000, tolerance=1e-16'
+);
+
+
+DROP TABLE IF EXISTS glm_predict_binomial_logit_out; CREATE TABLE glm_predict_binomial_logit_out as SELECT id, glm_model.sex, glm_predict(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'logit')
+FROM glm_model, abalone WHERE abalone.sex=glm_model.sex;
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', 'sex','bar ~ foo1+foo2+foo3+foo4+foo5+foo6');
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', 'sex','foo1+foo2+foo3+foo4+foo5+foo6');
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', 'sex','{foo1,foo2,foo3,foo4,foo5,foo6}');
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', 'sex','{bar,foo1,foo2,foo3,foo4,foo5,foo6,foo7,foo8}');
+
+DROP TABLE IF EXISTS glm_predict_binomial_logit_out; CREATE TABLE glm_predict_binomial_logit_out as SELECT id, glm_model.sex, glm_predict_binomial(coef, ARRAY[1, length, diameter, height, whole, shucked, viscera, shell], 'logit')
+FROM glm_model, abalone WHERE abalone.sex=glm_model.sex;
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_rings < 10', 'sex','foo1+foo2+foo3+foo4+foo5+foo6');
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_rings < 10', 'sex','{foo1,foo2,foo3,foo4,foo5,foo6}');
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_rings < 10', 'sex','{bar,foo1,foo2,foo3,foo4,foo5,foo6,foo7,foo8}');
+
+DROP TABLE IF EXISTS glm_model, glm_model_summary;
+SELECT glm(
+ 'abalone',
+ 'glm_model',
+ 'rings < 10',
+ 'ARRAY[length, diameter, height, whole, shucked, viscera, shell]',
+ 'family=binomial, link=logit', 'sex', 'max_iter=1000, tolerance=1e-16'
+);
+
+
+DROP TABLE IF EXISTS glm_predict_binomial_logit_out; CREATE TABLE glm_predict_binomial_logit_out as SELECT id, glm_model.sex, glm_predict(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'logit')
+FROM glm_model, abalone WHERE abalone.sex=glm_model.sex;
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', 'sex','bar ~ foo1+foo2+foo3+foo4+foo5+foo6');
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', 'sex','foo1+foo2+foo3+foo4+foo5+foo6');
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', 'sex','{foo1,foo2,foo3,foo4,foo5,foo6}');
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict', 'probability_true', 'sex','{bar,foo1,foo2,foo3,foo4,foo5,foo6,foo7,foo8}');
+
+DROP TABLE IF EXISTS glm_predict_binomial_logit_out; CREATE TABLE glm_predict_binomial_logit_out as SELECT id, glm_model.sex, glm_predict_binomial(coef, ARRAY[length, diameter, height, whole, shucked, viscera, shell], 'logit')
+FROM glm_model, abalone WHERE abalone.sex=glm_model.sex;
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_rings < 10', 'sex','foo1+foo2+foo3+foo4+foo5+foo6');
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_rings < 10', 'sex','{foo1,foo2,foo3,foo4,foo5,foo6}');
+SELECT test_pmml_output('abalone', 'glm_model', 'glm_predict_binomial_logit_out', 'id', 'glm_predict_binomial', 'predicted_rings < 10', 'sex','{bar,foo1,foo2,foo3,foo4,foo5,foo6,foo7,foo8}');
+
diff --git a/src/ports/postgres/modules/pmml/test/pmml_linear.sql_in b/src/ports/postgres/modules/pmml/test/pmml_linear.sql_in
new file mode 100644
index 00000000..a870e373
--- /dev/null
+++ b/src/ports/postgres/modules/pmml/test/pmml_linear.sql_in
@@ -0,0 +1,91 @@
+/* ----------------------------------------------------------------------- *//**
+ *
+ * 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.
+ *
+ *//* ----------------------------------------------------------------------- */
+
+ \i m4_regexp(MADLIB_LIBRARY_PATH, `\(.*\)/lib',
+ `\1/../modules/pmml/test/pmml.setup.sql_in'
+)
+
+m4_changequote(`<!'', `!>'')
+
+DROP TABLE IF EXISTS linregr_model, linregr_model_summary;
+SELECT linregr_train(
+ 'houses',
+ 'linregr_model',
+ 'price',
+ 'array[1, bedroom, bath, size]'
+);
+
+DROP TABLE IF EXISTS linregr_predict_output;
+CREATE TABLE linregr_predict_output AS
+ SELECT id, linregr_predict(coef, ARRAY[1, bedroom, bath, size])
+FROM linregr_model, houses;
+SELECT test_pmml_output('houses', 'linregr_model', 'linregr_predict_output', 'id', 'linregr_predict', 'predicted_price_pmml_prediction');
+
+
+DROP TABLE IF EXISTS linregr_model, linregr_model_summary;
+SELECT linregr_train(
+ 'houses',
+ 'linregr_model',
+ 'price',
+ 'array[1, bedroom, bath, size]',
+ 'g1, g2'
+);
+
+DROP TABLE IF EXISTS linregr_predict_output;
+CREATE TABLE linregr_predict_output AS
+ SELECT id, linregr_model.g1, linregr_model.g2,
+ linregr_predict(coef, ARRAY[1, bedroom, bath, size])
+FROM linregr_model, houses
+WHERE linregr_model.g1=houses.g1 AND linregr_model.g2=houses.g2;
+SELECT test_pmml_output('houses', 'linregr_model', 'linregr_predict_output', 'id', 'linregr_predict', 'predicted_price_pmml_prediction', 'g1,g2');
+
+---------------- without intercept ------------------------------
+DROP TABLE IF EXISTS linregr_model, linregr_model_summary;
+SELECT linregr_train(
+ 'houses',
+ 'linregr_model',
+ 'price',
+ 'array[bedroom, bath, size]'
+);
+
+DROP TABLE IF EXISTS linregr_predict_output;
+CREATE TABLE linregr_predict_output AS
+ SELECT id, linregr_predict(coef, ARRAY[bedroom, bath, size])
+FROM linregr_model, houses;
+SELECT test_pmml_output('houses', 'linregr_model', 'linregr_predict_output', 'id', 'linregr_predict', 'predicted_price_pmml_prediction');
+
+
+DROP TABLE IF EXISTS linregr_model, linregr_model_summary;
+SELECT linregr_train(
+ 'houses',
+ 'linregr_model',
+ 'price',
+ 'array[bedroom, bath, size]',
+ 'g1, g2'
+);
+
+DROP TABLE IF EXISTS linregr_predict_output;
+CREATE TABLE linregr_predict_output AS
+ SELECT id, linregr_model.g1, linregr_model.g2,
+ linregr_predict(coef, ARRAY[bedroom, bath, size])
+FROM linregr_model, houses
+WHERE linregr_model.g1=houses.g1 AND linregr_model.g2=houses.g2;
+SELECT test_pmml_output('houses', 'linregr_model', 'linregr_predict_output', 'id', 'linregr_predict', 'predicted_price_pmml_prediction', 'g1,g2');
diff --git a/src/ports/postgres/modules/pmml/test/pmml_logistic.sql_in b/src/ports/postgres/modules/pmml/test/pmml_logistic.sql_in
new file mode 100644
index 00000000..8e9f2cbd
--- /dev/null
+++ b/src/ports/postgres/modules/pmml/test/pmml_logistic.sql_in
@@ -0,0 +1,159 @@
+/* ----------------------------------------------------------------------- *//**
+ *
+ * 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.
+ *
+ *//* ----------------------------------------------------------------------- */
+
+ \i m4_regexp(MADLIB_LIBRARY_PATH, `\(.*\)/lib',
+ `\1/../modules/pmml/test/pmml.setup.sql_in'
+)
+
+m4_changequote(`<!'', `!>'')
+
+DROP TABLE IF EXISTS logregr_model, logregr_model_summary;
+SELECT logregr_train(
+ '"Patients"',
+ 'logregr_model',
+ '"Second_attack"',
+ 'ARRAY[1, "Treatment", trait_anxiety]',
+ NULL,
+ 20,
+ 'irls'
+);
+DROP TABLE IF EXISTS logregr_predict_output; CREATE TABLE logregr_predict_output as SELECT id, logregr_predict(coef, ARRAY[1, "Treatment", trait_anxiety])
+FROM logregr_model, "Patients";
+SELECT test_pmml_output('"Patients"', 'logregr_model', 'logregr_predict_output', 'id', 'logregr_predict', 'predicted_Second_attack_pmml_prediction');
+
+DROP TABLE IF EXISTS logregr_predict_output; CREATE TABLE logregr_predict_output as SELECT id, logregr_predict_prob(coef, ARRAY[1, "Treatment", trait_anxiety])
+FROM logregr_model, "Patients";
+SELECT test_pmml_output('"Patients"', 'logregr_model', 'logregr_predict_output', 'id', 'logregr_predict_prob', 'probability_true');
+
+--- simple grouping -------
+DROP TABLE IF EXISTS logregr_model_grouping, logregr_model_grouping_summary;
+SELECT logregr_train(
+ '"Patients"',
+ 'logregr_model_grouping',
+ '"Second_attack"',
+ 'ARRAY[1, "Treatment", trait_anxiety]',
+ 'g1',
+ 20,
+ 'irls'
+);
+DROP TABLE IF EXISTS logregr_predict_output; CREATE TABLE logregr_predict_output as SELECT id, logregr_model_grouping.g1, logregr_predict(coef, ARRAY[1, "Treatment", trait_anxiety])
+FROM logregr_model_grouping, "Patients" WHERE logregr_model_grouping.g1="Patients".g1;
+SELECT test_pmml_output('"Patients"', 'logregr_model_grouping', 'logregr_predict_output', 'id', 'logregr_predict', 'predicted_Second_attack_pmml_prediction', 'g1');
+
+DROP TABLE IF EXISTS logregr_predict_output; CREATE TABLE logregr_predict_output as SELECT id, logregr_model_grouping.g1, logregr_predict_prob(coef, ARRAY[1, "Treatment", trait_anxiety])
+FROM logregr_model_grouping, "Patients" WHERE logregr_model_grouping.g1="Patients".g1;
+SELECT test_pmml_output('"Patients"', 'logregr_model_grouping', 'logregr_predict_output', 'id', 'logregr_predict_prob', 'probability_true', 'g1');
+
+--- complex grouping -------
+DROP TABLE IF EXISTS logregr_model_grouping, logregr_model_grouping_summary;
+SELECT logregr_train(
+ '"Patients"',
+ 'logregr_model_grouping',
+ '"Second_attack"',
+ 'ARRAY[1, "Treatment", trait_anxiety]', -- test double quote
+ 'g1, g2',
+ 20,
+ 'irls'
+);
+DROP TABLE IF EXISTS logregr_predict_output; CREATE TABLE logregr_predict_output as SELECT id, logregr_model_grouping.g1, logregr_model_grouping.g2, logregr_predict(coef, ARRAY[1, "Treatment", trait_anxiety]) FROM logregr_model_grouping, "Patients"
+WHERE logregr_model_grouping.g1="Patients".g1 AND logregr_model_grouping.g2="Patients".g2;
+SELECT test_pmml_output('"Patients"', 'logregr_model_grouping', 'logregr_predict_output', 'id', 'logregr_predict', 'predicted_Second_attack_pmml_prediction', 'g1,g2');
+
+DROP TABLE IF EXISTS logregr_predict_output; CREATE TABLE logregr_predict_output as SELECT id, logregr_model_grouping.g1, logregr_model_grouping.g2, logregr_predict_prob(coef, ARRAY[1, "Treatment", trait_anxiety]) FROM logregr_model_grouping, "Patients"
+WHERE logregr_model_grouping.g1="Patients".g1 AND logregr_model_grouping.g2="Patients".g2;
+SELECT test_pmml_output('"Patients"', 'logregr_model_grouping', 'logregr_predict_output', 'id', 'logregr_predict_prob', 'probability_true', 'g1,g2');
+
+
+--------------------------- without intercept ------------------------------
+DROP TABLE IF EXISTS logregr_model, logregr_model_summary;
+SELECT logregr_train(
+ '"Patients"',
+ 'logregr_model',
+ '"Second_attack"',
+ 'ARRAY["Treatment", trait_anxiety]',
+ NULL,
+ 20,
+ 'irls'
+);
+DROP TABLE IF EXISTS logregr_predict_output; CREATE TABLE logregr_predict_output as SELECT id, logregr_predict(coef, ARRAY["Treatment", trait_anxiety])
+FROM logregr_model, "Patients";
+SELECT test_pmml_output('"Patients"', 'logregr_model', 'logregr_predict_output', 'id', 'logregr_predict', 'predicted_Second_attack_pmml_prediction');
+
+DROP TABLE IF EXISTS logregr_predict_output; CREATE TABLE logregr_predict_output as SELECT id, logregr_predict_prob(coef, ARRAY["Treatment", trait_anxiety])
+FROM logregr_model, "Patients";
+SELECT test_pmml_output('"Patients"', 'logregr_model', 'logregr_predict_output', 'id', 'logregr_predict_prob', 'probability_true');
+
+--- simple grouping -------
+DROP TABLE IF EXISTS logregr_model_grouping, logregr_model_grouping_summary;
+SELECT logregr_train(
+ '"Patients"',
+ 'logregr_model_grouping',
+ '"Second_attack"',
+ 'ARRAY["Treatment", trait_anxiety]',
+ 'g1',
+ 20,
+ 'irls'
+);
+DROP TABLE IF EXISTS logregr_predict_output; CREATE TABLE logregr_predict_output as SELECT id, logregr_model_grouping.g1, logregr_predict(coef, ARRAY["Treatment", trait_anxiety])
+FROM logregr_model_grouping, "Patients" WHERE logregr_model_grouping.g1="Patients".g1;
+SELECT test_pmml_output('"Patients"', 'logregr_model_grouping', 'logregr_predict_output', 'id', 'logregr_predict', 'predicted_Second_attack_pmml_prediction', 'g1');
+
+DROP TABLE IF EXISTS logregr_predict_output; CREATE TABLE logregr_predict_output as SELECT id, logregr_model_grouping.g1, logregr_predict_prob(coef, ARRAY["Treatment", trait_anxiety])
+FROM logregr_model_grouping, "Patients" WHERE logregr_model_grouping.g1="Patients".g1;
+SELECT test_pmml_output('"Patients"', 'logregr_model_grouping', 'logregr_predict_output', 'id', 'logregr_predict_prob', 'probability_true', 'g1');
+
+--- complex grouping -------
+DROP TABLE IF EXISTS logregr_model_grouping, logregr_model_grouping_summary;
+SELECT logregr_train(
+ '"Patients"',
+ 'logregr_model_grouping',
+ '"Second_attack"',
+ 'ARRAY["Treatment", trait_anxiety]', -- test double quote
+ 'g1, g2',
+ 20,
+ 'irls'
+);
+DROP TABLE IF EXISTS logregr_predict_output; CREATE TABLE logregr_predict_output as SELECT id, logregr_model_grouping.g1, logregr_model_grouping.g2, logregr_predict(coef, ARRAY["Treatment", trait_anxiety]) FROM logregr_model_grouping, "Patients"
+WHERE logregr_model_grouping.g1="Patients".g1 AND logregr_model_grouping.g2="Patients".g2;
+SELECT test_pmml_output('"Patients"', 'logregr_model_grouping', 'logregr_predict_output', 'id', 'logregr_predict', 'predicted_Second_attack_pmml_prediction', 'g1,g2');
+
+DROP TABLE IF EXISTS logregr_predict_output; CREATE TABLE logregr_predict_output as SELECT id, logregr_model_grouping.g1, logregr_model_grouping.g2, logregr_predict_prob(coef, ARRAY["Treatment", trait_anxiety]) FROM logregr_model_grouping, "Patients"
+WHERE logregr_model_grouping.g1="Patients".g1 AND logregr_model_grouping.g2="Patients".g2;
+SELECT test_pmml_output('"Patients"', 'logregr_model_grouping', 'logregr_predict_output', 'id', 'logregr_predict_prob', 'probability_true', 'g1,g2');
+
+--- with 0 intercept ---------
+DROP TABLE IF EXISTS logregr_model, logregr_model_summary;
+SELECT logregr_train(
+ '"Patients"',
+ 'logregr_model',
+ '"Second_attack"',
+ 'ARRAY[0, "Treatment", trait_anxiety]',
+ NULL,
+ 20,
+ 'irls'
+);
+DROP TABLE IF EXISTS logregr_predict_output; CREATE TABLE logregr_predict_output as SELECT id, logregr_predict(coef, ARRAY[0, "Treatment", trait_anxiety])
+FROM logregr_model, "Patients";
+SELECT test_pmml_output('"Patients"', 'logregr_model', 'logregr_predict_output', 'id', 'logregr_predict', 'predicted_Second_attack_pmml_prediction');
+
+DROP TABLE IF EXISTS logregr_predict_output; CREATE TABLE logregr_predict_output as SELECT id, logregr_predict_prob(coef, ARRAY[0, "Treatment", trait_anxiety])
+FROM logregr_model, "Patients";
+SELECT test_pmml_output('"Patients"', 'logregr_model', 'logregr_predict_output', 'id', 'logregr_predict_prob', 'probability_true');
diff --git a/src/ports/postgres/modules/pmml/test/pmml_multinom.sql_in b/src/ports/postgres/modules/pmml/test/pmml_multinom.sql_in
index 763ebd62..576d96ac 100644
--- a/src/ports/postgres/modules/pmml/test/pmml_multinom.sql_in
+++ b/src/ports/postgres/modules/pmml/test/pmml_multinom.sql_in
@@ -1,3 +1,10 @@
+\i m4_regexp(MADLIB_LIBRARY_PATH,
+ `\(.*\)/lib',
+ `\1/../modules/pmml/test/pmml.setup.sql_in'
+)
+
+m4_changequote(`<!'', `!>'')
+
DROP TABLE IF EXISTS multinom_test;
CREATE TABLE multinom_test (
feat1 INTEGER,
@@ -207,6 +214,7 @@ INSERT INTO multinom_test(feat1, feat2, cat, g) VALUES
(2,67,2,'B'),
(2,65,2,'B'),
(2,62,2,'B');
+ALTER TABLE multinom_test ADD COLUMN id SERIAL;
DROP TABLE IF EXISTS mglm_out, mglm_out_summary;
SELECT multinom(
@@ -216,8 +224,16 @@ SELECT multinom(
'ARRAY[1, feat1, feat2]',
'0',
'logit');
+DROP TABLE IF EXISTS multinom_predict_out; SELECT multinom_predict('mglm_out','multinom_test', 'multinom_predict_out', 'probability',FALSE,'id');
+SELECT test_pmml_output('multinom_test', 'mglm_out', 'multinom_predict_out', 'id', '0', 'probability_0');
+SELECT test_pmml_output('multinom_test', 'mglm_out', 'multinom_predict_out', 'id', '1', 'probability_1');
+SELECT test_pmml_output('multinom_test', 'mglm_out', 'multinom_predict_out', 'id', '2', 'probability_2');
-DROP TABLE IF EXISTS mglm_grp_out, mglm_grp_out_summary;
+DROP TABLE IF EXISTS multinom_predict_out; SELECT multinom_predict('mglm_out','multinom_test', 'multinom_predict_out', 'response',FALSE,'id');
+SELECT test_pmml_output('multinom_test', 'mglm_out', 'multinom_predict_out', 'id', 'category', 'predicted_cat_pmml_prediction');
+
+------------------------------------ with grouping -------------------------------------------------------------------
+-- DROP TABLE IF EXISTS mglm_grp_out, mglm_grp_out_summary;
SELECT multinom(
'multinom_test',
'mglm_grp_out',
@@ -228,5 +244,10 @@ SELECT multinom(
'g');
-- PMML export
-SELECT pmml('mglm_out');
SELECT pmml('mglm_grp_out');
+DROP TABLE IF EXISTS multinom_predict_out; SELECT multinom_predict('mglm_grp_out','multinom_test', 'multinom_predict_out', 'probability',FALSE,'id');
+CREATE TABLE multinom_predict_grp_out as (SELECT a.id, a.g, b."0", b."1", b."2", a.feat1, a.feat2 FROM multinom_test AS a LEFT JOIN multinom_predict_out AS b on a.id =b.id);
+SELECT test_pmml_output('multinom_test', 'mglm_grp_out', 'multinom_predict_grp_out', 'id', '0', 'probability_0','g');
+
+DROP TABLE IF EXISTS multinom_predict_out; SELECT multinom_predict('mglm_grp_out','multinom_test', 'multinom_predict_out', 'response',FALSE,'id');
+SELECT test_pmml_output('multinom_test', 'mglm_grp_out', 'multinom_predict_out', 'id', 'category', 'predicted_cat_pmml_prediction');
diff --git a/src/ports/postgres/modules/pmml/test/pmml_with_non_array_expression.sql_in b/src/ports/postgres/modules/pmml/test/pmml_with_non_array_expression.sql_in
new file mode 100644
index 00000000..1a7769d7
--- /dev/null
+++ b/src/ports/postgres/modules/pmml/test/pmml_with_non_array_expression.sql_in
@@ -0,0 +1,94 @@
+/* ----------------------------------------------------------------------- *//**
+ *
+ * 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.
+ *
+ *//* ----------------------------------------------------------------------- */
+
+ \i m4_regexp(MADLIB_LIBRARY_PATH, `\(.*\)/lib',
+ `\1/../modules/pmml/test/pmml.setup.sql_in'
+)
+
+m4_changequote(`<!'', `!>'')
+
+----------------------- Use non array expression for the features argument -------------------------------
+
+--------------- glm --------------
+CREATE TABLE abalone_non_array_expression as SELECT id, sex, rings < 10 as target,ARRAY[1, length, diameter, height, whole, shucked, viscera, shell] as features from abalone;
+
+DROP TABLE IF EXISTS glm_model, glm_model_summary;
+SELECT glm(
+ 'abalone_non_array_expression',
+ 'glm_model',
+ 'target',
+ 'features',
+ 'family=binomial, link=logit', '', 'max_iter=1000, tolerance=1e-16'
+);
+
+-- Test probabilities
+-- The feature names in output pmml will look like "features[1], features[2]" and so on. So pypmml also needs to predict using the same names, hence the table creation
+CREATE TABLE abalone_test_for_pmml1 as SELECT id, sex, length as "features[1]", diameter as "features[2]", height as "features[3]", whole as "features[4]", shucked as "features[5]", viscera as "features[6]",shell as "features[7]" from abalone;
+
+DROP TABLE IF EXISTS glm_predict_output; CREATE TABLE glm_predict_output as SELECT id, glm_predict(coef, features, 'logit') FROM glm_model, abalone_non_array_expression;
+SELECT test_pmml_output('abalone_test_for_pmml1', 'glm_model', 'glm_predict_output', 'id', 'glm_predict', 'probability_true');
+
+-- Test output category
+DROP TABLE IF EXISTS glm_predict_output; CREATE TABLE glm_predict_output as SELECT id, glm_predict_binomial(coef, features, 'logit') FROM glm_model, abalone_non_array_expression;
+SELECT test_pmml_output('abalone_test_for_pmml1', 'glm_model', 'glm_predict_output', 'id', 'glm_predict_binomial', 'predicted_target_pmml_prediction');
+
+--------------- logistic regression --------------
+CREATE TABLE patients_non_array_expression AS SELECT id, "Second_attack" AS y, ARRAY[1, "Treatment", trait_anxiety] AS "x_A" FROM "Patients";
+
+DROP TABLE IF EXISTS logregr_model, logregr_model_summary;
+SELECT logregr_train(
+ 'patients_non_array_expression',
+ 'logregr_model',
+ 'y',
+ '"x_A"');
+
+-- The feature names in output pmml will look like "features[1], features[2]" and so on. So pypmml also needs to predict using the same names, hence the table creation
+CREATE TABLE patients_test_for_pmml as SELECT id, "Treatment" as "x_A[1]", trait_anxiety as "x_A[2]" FROM "Patients";
+
+DROP TABLE IF EXISTS logregr_predict_output; CREATE TABLE logregr_predict_output as SELECT id, logregr_predict(coef, "x_A") FROM logregr_model, patients_non_array_expression;
+SELECT test_pmml_output('patients_test_for_pmml', 'logregr_model', 'logregr_predict_output', 'id', 'logregr_predict', 'predicted_y_pmml_prediction');
+
+DROP TABLE IF EXISTS logregr_predict_output; CREATE TABLE logregr_predict_output as SELECT id, logregr_predict_prob(coef, "x_A") FROM logregr_model, patients_non_array_expression;
+SELECT test_pmml_output('patients_test_for_pmml', 'logregr_model', 'logregr_predict_output', 'id', 'logregr_predict_prob', 'probability_true');
+
+
+------------------------------------------ now with grouping and name spec------------------------------------------------
+
+DROP TABLE IF EXISTS glm_model, glm_model_summary;
+SELECT glm(
+ 'abalone_non_array_expression',
+ 'glm_model',
+ 'target',
+ 'features',
+ 'family=binomial, link=probit', 'sex,id', 'max_iter=1000, tolerance=1e-16'
+);
+
+CREATE TABLE abalone_test_for_pmml2 as SELECT id, sex, length as foo1, diameter as foo2, height as foo3, whole as foo4, shucked as foo5, viscera as foo6,shell as foo7 from abalone;
+
+-- -- Test probabilities
+DROP TABLE IF EXISTS glm_predict_output; CREATE TABLE glm_predict_output as SELECT glm_model.id, glm_model.sex, glm_predict(coef, features, 'probit') FROM glm_model, abalone_non_array_expression
+WHERE abalone_non_array_expression.id=glm_model.id AND abalone_non_array_expression.sex=glm_model.sex;
+SELECT test_pmml_output('abalone_test_for_pmml2', 'glm_model', 'glm_predict_output', 'id', 'glm_predict', 'probability_true', 'sex,id', 'bar ~ foo1+foo2+foo3+foo4+foo5+foo6+foo7');
+
+-- Test output category
+DROP TABLE IF EXISTS glm_predict_output; CREATE TABLE glm_predict_output as SELECT glm_model.id, glm_model.sex, glm_predict_binomial(coef, features, 'probit') FROM glm_model, abalone_non_array_expression
+WHERE abalone_non_array_expression.id=glm_model.id AND abalone_non_array_expression.sex=glm_model.sex;
+SELECT test_pmml_output('abalone_test_for_pmml2', 'glm_model', 'glm_predict_output', 'id', 'glm_predict_binomial', 'predicted_bar', 'sex,id', 'bar ~ foo1+foo2+foo3+foo4+foo5+foo6+foo7');
diff --git a/src/ports/postgres/modules/pmml/test/table_to_pmml.sql_in b/src/ports/postgres/modules/pmml/test/table_to_pmml.sql_in
deleted file mode 100644
index bcdc3181..00000000
--- a/src/ports/postgres/modules/pmml/test/table_to_pmml.sql_in
+++ /dev/null
@@ -1,197 +0,0 @@
----------------------------------------------------------------------------
--- logregr
----------------------------------------------------------------------------
-CREATE TABLE "Patients" (
- id integer NOT NULL,
- "Second_attack" integer,
- "Treatment" integer,
- trait_anxiety integer,
- g1 char(1),
- g2 char(1)
-);
-
-INSERT INTO "Patients"(ID, "Second_attack", "Treatment", trait_anxiety, g1, g2) VALUES
-( 1, 1, 1, 70, 'A', 'x'),
-( 2, 1, 1, 80, 'A', 'y'),
-( 3, 1, 1, 50, 'A', 'y'),
-( 4, 1, 0, 60, 'A', 'y'),
-( 5, 1, 0, 40, 'A', 'y'),
-( 6, 1, 0, 65, 'A', 'x'),
-( 7, 1, 0, 75, 'A', 'x'),
-( 8, 1, 0, 80, 'B', 'x'),
-( 9, 1, 0, 70, 'A', 'x'),
-(10, 1, 0, 60, 'A', 'z'),
-(11, 0, 1, 65, 'A', 'z'),
-(12, 0, 1, 50, 'B', 'y'),
-(13, 0, 1, 45, 'A', 'y'),
-(14, 0, 1, 35, 'A', 'z'),
-(15, 0, 1, 40, 'A', 'z'),
-(16, 0, 1, 50, 'A', 'z'),
-(17, 0, 0, 55, 'B', 'z'),
-(18, 0, 0, 45, 'B', 'z'),
-(19, 0, 0, 50, 'B', 'z'),
-(20, 0, 0, 60, 'B', 'z');
-
-SELECT logregr_train(
- '"Patients"',
- 'no_grouping',
- '"Second_attack"',
- 'ARRAY[1, "Treatment", trait_anxiety]',
- NULL,
- 20,
- 'irls'
-);
-
-SELECT logregr_train(
- '"Patients"',
- 'simple_grouping',
- '"Second_attack"',
- 'ARRAY[1, "Treatment", trait_anxiety]',
- 'g1',
- 20,
- 'irls'
-);
-
-
-SELECT logregr_train(
- '"Patients"',
- 'complex_grouping',
- '"Second_attack"',
- 'ARRAY[1, "Treatment", trait_anxiety]', -- test double quote
- 'g1, g2',
- 20,
- 'irls'
-);
-
-
-SELECT pmml('no_grouping');
-SELECT pmml('simple_grouping');
-SELECT pmml('complex_grouping');
-
--- test simple column
-CREATE TABLE pmml_logregr_example AS
-SELECT "Second_attack" AS y, ARRAY[1, "Treatment", trait_anxiety] AS "x_A"
-FROM "Patients";
-
-SELECT logregr_train('pmml_logregr_example', 'example_pmml', 'y', '"x_A"');
-SELECT pmml('example_pmml');
-
----------------------------------------------------------------------------
--- linregr
----------------------------------------------------------------------------
-CREATE TABLE houses (
- id SERIAL NOT NULL,
- tax INTEGER,
- bedroom REAL,
- bath REAL,
- price INTEGER,
- size INTEGER,
- lot INTEGER,
- g1 CHAR(1),
- g2 CHAR(1)
-);
-
-INSERT INTO houses(tax, bedroom, bath, price, size, lot, g1, g2) VALUES
-( 590, 2, 1, 50000, 770, 22100, 'A', 'z'),
-(1050, 3, 2, 85000, 1410, 12000, 'A', 'y'),
-( 20, 3, 1, 22500, 1060, 3500 , 'A', 'y'),
-( 870, 2, 2, 90000, 1300, 17500, 'A', 'y'),
-(1320, 3, 2, 133000, 1500, 30000, 'A', 'y'),
-(1350, 2, 1, 90500, 820, 25700, 'A', 'x'),
-(2790, 3, 2.5, 260000, 2130, 25000, 'A', 'x'),
-( 680, 2, 1, 142500, 1170, 22000, 'A', 'x'),
-(1840, 3, 2, 160000, 1500, 19000, 'B', 'x'),
-(3680, 4, 2, 240000, 2790, 20000, 'B', 'y'),
-(1660, 3, 1, 87000, 1030, 17500, 'B', 'y'),
-(1620, 3, 2, 118600, 1250, 20000, 'A', 'y'),
-(3100, 3, 2, 140000, 1760, 38000, 'B', 'y'),
-(2070, 2, 3, 148000, 1550, 14000, 'B', 'y'),
-( 650, 3, 1.5, 65000, 1450, 12000, 'B', 'y');
-
-SELECT linregr_train(
- 'houses',
- 'linregr_grouping',
- 'price',
- 'array[1, bedroom, bath, size]',
- 'g1, g2'
-);
-
-SELECT pmml('linregr_grouping');
-
-
-CREATE OR REPLACE FUNCTION count_expected_names(formula varchar, expected varchar[])
-RETURNS bigint AS $$
- SELECT count(distinct result.name)
- FROM
- (SELECT text(unnest(xpath('/n:PMML/n:DataDictionary/n:DataField/@name',
- pmml_col, ARRAY[ARRAY['n', 'http://www.dmg.org/PMML-4_1']]))) AS name
- FROM (SELECT CASE WHEN $1 is NULL THEN pmml('linregr_grouping')
- ELSE pmml('linregr_grouping', $1)
- END AS pmml_col) linregr_grouping_pmml
- ) result,
- (SELECT unnest($2) AS name) expected
- WHERE expected.name = result.name;
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION count_expected_names(name_spec varchar[], expected varchar[])
-RETURNS bigint AS $$
- SELECT count(distinct result.name)
- FROM
- (SELECT text(unnest(xpath('/n:PMML/n:DataDictionary/n:DataField/@name',
- pmml_col, ARRAY[ARRAY['n', 'http://www.dmg.org/PMML-4_1']]))) AS name
- FROM (SELECT CASE WHEN $1 is NULL THEN pmml('linregr_grouping')
- ELSE pmml('linregr_grouping', $1)
- END AS pmml_col) linregr_grouping_pmml
- ) result,
- (SELECT unnest($2) AS name) expected
- WHERE expected.name = result.name;
-$$ LANGUAGE sql;
-
-
-
-SELECT assert(
- count_expected_names(
- NULL,
- ARRAY['price_pmml_prediction', '1', 'bedroom', 'bath', 'size', 'g1', 'g2']
- ) = 7,
- 'default case');
-
-SELECT assert(
- count_expected_names(
- 'c.price ~ c.1 + c.bedroom + c.bath + c.size',
- ARRAY['c.price', 'c.1', 'c.bedroom', 'c.bath', 'c.size']
- ) = 5,
- text(pmml('linregr_grouping',
- 'c.price ~ c.1 + c.bedroom + c.bath + c.size')));
-
-SELECT assert(
- count_expected_names(
- '{c.price, c.1, c.bedroom, c.bath, c.size}'::varchar[],
- ARRAY['c.price', 'c.1', 'c.bedroom', 'c.bath', 'c.size']
- ) = 5,
- text(pmml('linregr_grouping',
- 'c.price ~ c.1 + c.bedroom + c.bath + c.size')));
-
-SELECT assert(
- count_expected_names(
- '{c.price, c.1, c.bedroom, c.bath, c.size}',
- ARRAY['c.price', 'c.1', 'c.bedroom', 'c.bath', 'c.size']
- ) = 5,
- text(pmml('linregr_grouping',
- 'c.price ~ c.1 + c.bedroom + c.bath + c.size')));
-
-SELECT assert(
- count_expected_names(
- 'c.1 + c.bedroom + c.bath + c.size',
- ARRAY['price', 'c.1', 'c.bedroom', 'c.bath', 'c.size']
- ) = 5,
- text(pmml('linregr_grouping',
- 'c.1 + c.bedroom + c.bath + c.size')));
-
-SELECT assert(
- count_expected_names(
- 'c.1, c.bedroom, c.bath, c.size',
- ARRAY['price', 'c.1', 'c.bedroom', 'c.bath', 'c.size']
- ) = 5,
- text(pmml('linregr_grouping',
- 'c.1, c.bedroom, c.bath, c.size')));