You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@systemml.apache.org by du...@apache.org on 2016/09/01 17:13:39 UTC

incubator-systemml git commit: [SYSTEMML-889] Remove MLContext Java input output methods

Repository: incubator-systemml
Updated Branches:
  refs/heads/master d5eea2e85 -> 10e701de3


[SYSTEMML-889] Remove MLContext Java input output methods

This removes the `Script.input` and `Script.output` methods on the JVM
side, and hacks the Python side so that it is able to call the
`Script.in` method on the JVM side.  This means that a Scala/Java user
would use the clean `in(...)` and `out(...)` syntax, while a Python
user would use the `input(...)` and `output(...)` syntax.

Closes #229.


Project: http://git-wip-us.apache.org/repos/asf/incubator-systemml/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-systemml/commit/10e701de
Tree: http://git-wip-us.apache.org/repos/asf/incubator-systemml/tree/10e701de
Diff: http://git-wip-us.apache.org/repos/asf/incubator-systemml/diff/10e701de

Branch: refs/heads/master
Commit: 10e701de3fc145f83303afd3d609d7cb720a25a0
Parents: d5eea2e
Author: Mike Dusenberry <mw...@us.ibm.com>
Authored: Thu Sep 1 10:13:03 2016 -0700
Committer: Mike Dusenberry <mw...@us.ibm.com>
Committed: Thu Sep 1 10:13:03 2016 -0700

----------------------------------------------------------------------
 docs/beginners-guide-python.md                  |   2 +-
 .../org/apache/sysml/api/mlcontext/Script.java  | 112 -------------------
 src/main/python/SystemML/defmatrix.py           | 102 ++++++++---------
 src/main/python/SystemML/mlcontext.py           |  38 ++++---
 src/main/python/tests/test_mlcontext.py         |  18 +--
 5 files changed, 83 insertions(+), 189 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/10e701de/docs/beginners-guide-python.md
----------------------------------------------------------------------
diff --git a/docs/beginners-guide-python.md b/docs/beginners-guide-python.md
index b565656..3b4aeed 100644
--- a/docs/beginners-guide-python.md
+++ b/docs/beginners-guide-python.md
@@ -328,6 +328,6 @@ X_df = sqlCtx.createDataFrame(pd.DataFrame(X_digits[:.9 * n_samples]))
 y_df = sqlCtx.createDataFrame(pd.DataFrame(y_digits[:.9 * n_samples]))
 ml = sml.MLContext(sc)
 script = os.path.join(os.environ['SYSTEMML_HOME'], 'scripts', 'algorithms', 'MultiLogReg.dml')
-script = sml.dml(script).input(X=X_df, Y_vec=y_df).input(**{"$X": ' ', "$Y": ' ', "$B": ' '}).out("B_out")
+script = sml.dml(script).input(X=X_df, Y_vec=y_df).output("B_out")
 beta = ml.execute(script).getNumPyArray('B_out')
 ```

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/10e701de/src/main/java/org/apache/sysml/api/mlcontext/Script.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/api/mlcontext/Script.java b/src/main/java/org/apache/sysml/api/mlcontext/Script.java
index a3ce430..bfa947c 100644
--- a/src/main/java/org/apache/sysml/api/mlcontext/Script.java
+++ b/src/main/java/org/apache/sysml/api/mlcontext/Script.java
@@ -247,17 +247,6 @@ public class Script {
 	}
 
 	/**
-	 * Pass a map of inputs to the script.
-	 *
-	 * @param inputs
-	 *            map of inputs (parameters ($) and variables).
-	 * @return {@code this} Script object to allow chaining of methods
-	 */
-	public Script input(Map<String, Object> inputs) {
-		return in(inputs);
-	}
-
-	/**
 	 * Pass a Scala Map of inputs to the script.
 	 * <p>
 	 * Note that the {@code Map} value type is not explicitly specified on this
@@ -282,26 +271,6 @@ public class Script {
 	}
 
 	/**
-	 * Pass a Scala Map of inputs to the script.
-	 * <p>
-	 * Note that the {@code Map} value type is not explicitly specified on this
-	 * method because {@code [String, Any]} can't be recognized on the Java side
-	 * since {@code Any} doesn't have an equivalent in the Java class hierarchy
-	 * ({@code scala.Any} is a superclass of {@code scala.AnyRef}, which is
-	 * equivalent to {@code java.lang.Object}). Therefore, specifying
-	 * {@code scala.collection.Map<String, Object>} as an input parameter to
-	 * this Java method is not encompassing enough and would require types such
-	 * as a {@code scala.Double} to be cast using {@code asInstanceOf[AnyRef]}.
-	 *
-	 * @param inputs
-	 *            Scala Map of inputs (parameters ($) and variables).
-	 * @return {@code this} Script object to allow chaining of methods
-	 */
-	public Script input(scala.collection.Map<String, ?> inputs) {
-		return in(inputs);
-	}
-
-	/**
 	 * Pass a Scala Seq of inputs to the script. The inputs are either two-value
 	 * or three-value tuples, where the first value is the variable name, the
 	 * second value is the variable value, and the third optional value is the
@@ -330,20 +299,6 @@ public class Script {
 	}
 
 	/**
-	 * Pass a Scala Seq of inputs to the script. The inputs are either two-value
-	 * or three-value tuples, where the first value is the variable name, the
-	 * second value is the variable value, and the third optional value is the
-	 * metadata.
-	 *
-	 * @param inputs
-	 *            Scala Seq of inputs (parameters ($) and variables).
-	 * @return {@code this} Script object to allow chaining of methods
-	 */
-	public Script input(scala.collection.Seq<Object> inputs) {
-		return in(inputs);
-	}
-
-	/**
 	 * Obtain an unmodifiable map of all input parameters ($).
 	 *
 	 * @return input parameters ($)
@@ -366,19 +321,6 @@ public class Script {
 	}
 
 	/**
-	 * Register an input (parameter ($) or variable).
-	 *
-	 * @param name
-	 *            name of the input
-	 * @param value
-	 *            value of the input
-	 * @return {@code this} Script object to allow chaining of methods
-	 */
-	public Script input(String name, Object value) {
-		return in(name, value);
-	}
-
-	/**
 	 * Register an input (parameter ($) or variable) with optional matrix
 	 * metadata.
 	 *
@@ -403,22 +345,6 @@ public class Script {
 	 *            name of the input
 	 * @param value
 	 *            value of the input
-	 * @param matrixFormat
-	 *            optional matrix format
-	 * @return {@code this} Script object to allow chaining of methods
-	 */
-	public Script input(String name, Object value, MatrixFormat matrixFormat) {
-		return in(name, value, matrixFormat);
-	}
-
-	/**
-	 * Register an input (parameter ($) or variable) with optional matrix
-	 * metadata.
-	 *
-	 * @param name
-	 *            name of the input
-	 * @param value
-	 *            value of the input
 	 * @param matrixMetadata
 	 *            optional matrix metadata
 	 * @return {@code this} Script object to allow chaining of methods
@@ -473,22 +399,6 @@ public class Script {
 	}
 
 	/**
-	 * Register an input (parameter ($) or variable) with optional matrix
-	 * metadata.
-	 *
-	 * @param name
-	 *            name of the input
-	 * @param value
-	 *            value of the input
-	 * @param matrixMetadata
-	 *            optional matrix metadata
-	 * @return {@code this} Script object to allow chaining of methods
-	 */
-	public Script input(String name, Object value, MatrixMetadata matrixMetadata) {
-		return in(name, value, matrixMetadata);
-	}
-
-	/**
 	 * Register an output variable.
 	 *
 	 * @param outputName
@@ -501,17 +411,6 @@ public class Script {
 	}
 
 	/**
-	 * Register an output variable.
-	 *
-	 * @param outputName
-	 *            name of the output variable
-	 * @return {@code this} Script object to allow chaining of methods
-	 */
-	public Script output(String outputName) {
-		return out(outputName);
-	}
-
-	/**
 	 * Register output variables.
 	 *
 	 * @param outputNames
@@ -524,17 +423,6 @@ public class Script {
 	}
 
 	/**
-	 * Register output variables.
-	 *
-	 * @param outputNames
-	 *            names of the output variables
-	 * @return {@code this} Script object to allow chaining of methods
-	 */
-	public Script output(String... outputNames) {
-		return output(outputNames);
-	}
-
-	/**
 	 * Clear the inputs, outputs, and symbol table.
 	 */
 	public void clearIOS() {

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/10e701de/src/main/python/SystemML/defmatrix.py
----------------------------------------------------------------------
diff --git a/src/main/python/SystemML/defmatrix.py b/src/main/python/SystemML/defmatrix.py
index 37e813c..18f6314 100644
--- a/src/main/python/SystemML/defmatrix.py
+++ b/src/main/python/SystemML/defmatrix.py
@@ -30,7 +30,7 @@ from pyspark.sql import DataFrame, SQLContext
 def setSparkContext(sc):
     """
     Before using the matrix, the user needs to invoke this function.
-    
+
     Parameters
     ----------
     sc: SparkContext
@@ -38,7 +38,7 @@ def setSparkContext(sc):
     """
     matrix.ml = MLContext(sc)
     matrix.sc = sc
-    
+
 def checkIfMLContextIsSet():
     if matrix.ml is None:
         raise Exception('Expected setSparkContext(sc) to be called.')
@@ -50,10 +50,10 @@ class DMLOp(object):
     def __init__(self, inputs, dml=None):
         self.inputs = inputs
         self.dml = dml
-        
+
     def _visit(self, execute=True):
         matrix.dml = matrix.dml + self.dml
-            
+
 
 def reset():
     """
@@ -62,7 +62,7 @@ def reset():
     for m in matrix.visited:
         m.visited = False
     matrix.visited = []
-        
+
 def binaryOp(lhs, rhs, opStr):
     """
     Common function called by all the binary operators in matrix class
@@ -103,7 +103,7 @@ def binaryMatrixFunction(X, Y, fnName):
 def solve(A, b):
     """
     Computes the least squares solution for system of linear equations A %*% x = b
-    
+
     Examples
     --------
     >>> import numpy as np
@@ -123,7 +123,7 @@ def solve(A, b):
     >>> b = X.transpose().dot(y)
     >>> beta = sml.solve(A, b).toNumPyArray()
     >>> y_predicted = X_test.dot(beta)
-    >>> print('Residual sum of squares: %.2f' % np.mean((y_predicted - y_test) ** 2)) 
+    >>> print('Residual sum of squares: %.2f' % np.mean((y_predicted - y_test) ** 2))
     Residual sum of squares: 25282.12
     """
     return binaryMatrixFunction(A, b, 'solve')
@@ -158,20 +158,20 @@ def eval(outputs, outputDF=False, execute=True):
             m.data = results.getDataFrame(m.ID)
         else:
             m.data = results.getNumPyArray(m.ID)
-    
+
 class matrix(object):
     """
     matrix class is a python wrapper that implements basic matrix operator.
     Note: an evaluated matrix contains a data field computed by eval method as DataFrame or NumPy array.
-    
+
     Examples
     --------
     >>> import SystemML as sml
     >>> import numpy as np
     >>> sml.setSparkContext(sc)
-    
+
     Welcome to Apache SystemML!
-    
+
     >>> m1 = sml.matrix(np.ones((3,3)) + 2)
     >>> m2 = sml.matrix(np.ones((3,3)) + 3)
     >>> m2 = m1 * (m2 + m1)
@@ -184,7 +184,7 @@ class matrix(object):
     mVar4 = mVar1 * mVar3
     mVar5 = 1.0 - mVar4
     save(mVar5, " ")
-    
+
     <SystemML.defmatrix.matrix object>
     >>> m2.eval()
     >>> m2
@@ -195,7 +195,7 @@ class matrix(object):
     mVar4 = load(" ", format="csv")
     mVar5 = 1.0 - mVar4
     save(mVar5, " ")
-    
+
     <SystemML.defmatrix.matrix object>
     >>> m4.sum(axis=1).toNumPyArray()
     array([[-60.],
@@ -204,31 +204,31 @@ class matrix(object):
     """
     # Global variable that is used to keep track of intermediate matrix variables in the DML script
     systemmlVarID = 0
-    
+
     # Since joining of string is expensive operation, we collect the set of strings into list and then join
     # them before execution: See matrix.script.scriptString = ''.join(matrix.dml) in eval() method
     dml = []
-    
+
     # Represents MLContext's script object
     script = None
-    
+
     # Represents MLContext object
     ml = None
-    
+
     # Contains list of nodes visited in Abstract Syntax Tree. This helps to avoid computation of matrix objects
     # that have been previously evaluated.
     visited = []
-    
+
     def __init__(self, data, op=None):
         """
         Constructs a lazy matrix
-        
+
         Parameters
         ----------
         data: NumPy ndarray, Pandas DataFrame, scipy sparse matrix or PySpark DataFrame. (data cannot be None for external users, 'data=None' is used internally for lazy evaluation).
         """
         checkIfMLContextIsSet()
-        self.visited = False 
+        self.visited = False
         matrix.systemmlVarID += 1
         self.output = False
         self.ID = 'mVar' + str(matrix.systemmlVarID)
@@ -242,21 +242,21 @@ class matrix(object):
             self.op = op
         else:
             raise TypeError('Unsupported input type')
-            
+
     def eval(self, outputDF=False):
         """
         This is a convenience function that calls the global eval method
         """
         eval([self], outputDF=False)
-      
+
     def toPandas(self):
         """
         This is a convenience function that calls the global eval method and then converts the matrix object into Pandas DataFrame.
         """
         if self.data is None:
             self.eval()
-        return convertToPandasDF(self.data)    
-    
+        return convertToPandasDF(self.data)
+
     def toNumPyArray(self):
         """
         This is a convenience function that calls the global eval method and then converts the matrix object into NumPy array.
@@ -267,7 +267,7 @@ class matrix(object):
             self.data = self.data.toPandas().as_matrix()
         # Always keep default format as NumPy array if possible
         return self.data
-    
+
     def toDataFrame(self):
         """
         This is a convenience function that calls the global eval method and then converts the matrix object into DataFrame.
@@ -279,13 +279,13 @@ class matrix(object):
                 MLResults.sqlContext = SQLContext(matrix.sc)
             self.data = sqlContext.createDataFrame(self.toPandas())
         return self.data
-        
+
     def _visit(self, execute=True):
         """
         This function is called for two scenarios:
         1. For printing the PyDML script which has not yet been evaluated (execute=False). See '__repr__' method.
-        2. Called as part of 'eval' method (execute=True). In this scenario, it builds the PyDML script by visiting itself 
-        and its child nodes. Also, it does appropriate registration as input or output that is required by MLContext.  
+        2. Called as part of 'eval' method (execute=True). In this scenario, it builds the PyDML script by visiting itself
+        and its child nodes. Also, it does appropriate registration as input or output that is required by MLContext.
         """
         if self.visited:
             return self
@@ -308,13 +308,13 @@ class matrix(object):
         if self.data is None and self.output:
             matrix.dml = matrix.dml + ['save(',  self.ID, ', \" \")\n']
             if execute:
-                matrix.script.out(self.ID)
+                matrix.script.output(self.ID)
         return self
-    
+
     def __repr__(self):
         """
         This function helps to debug matrix class and also examine the generated PyDML script
-        """ 
+        """
         if self.data is None:
             print('# This matrix (' + self.ID + ') is backed by below given PyDML script (which is not yet evaluated). To fetch the data of this matrix, invoke toNumPyArray() or toDataFrame() or toPandas() methods.\n' + eval([self], execute=False))
         elif isinstance(self.data, DataFrame):
@@ -322,49 +322,49 @@ class matrix(object):
         else:
             print('# This matrix (' + self.ID + ') is backed by NumPy array. To fetch the NumPy array, invoke toNumPyArray() method.')
         return '<SystemML.defmatrix.matrix object>'
-        
+
     def __add__(self, other):
         return binaryOp(self, other, ' + ')
-        
+
     def __sub__(self, other):
         return binaryOp(self, other, ' - ')
-        
+
     def __mul__(self, other):
         return binaryOp(self, other, ' * ')
-        
+
     def __floordiv__(self, other):
         return binaryOp(self, other, ' // ')
-        
+
     def __div__(self, other):
         return binaryOp(self, other, ' / ')
-        
+
     def __mod__(self, other):
         return binaryOp(self, other, ' % ')
-        
+
     def __pow__(self, other):
         return binaryOp(self, other, ' ** ')
 
     def __radd__(self, other):
         return binaryOp(other, self, ' + ')
-        
+
     def __rsub__(self, other):
         return binaryOp(other, self, ' - ')
-        
+
     def __rmul__(self, other):
         return binaryOp(other, self, ' * ')
-        
+
     def __rfloordiv__(self, other):
         return binaryOp(other, self, ' // ')
-        
+
     def __rdiv__(self, other):
         return binaryOp(other, self, ' / ')
-        
+
     def __rmod__(self, other):
         return binaryOp(other, self, ' % ')
-        
+
     def __rpow__(self, other):
         return binaryOp(other, self, ' ** ')
-        
+
     def sum(self, axis=None):
         return self._aggFn('sum', axis)
 
@@ -382,7 +382,7 @@ class matrix(object):
 
     def argmax(self, axis=None):
         return self._aggFn('argmax', axis)
-        
+
     def cumsum(self, axis=None):
         return self._aggFn('cumsum', axis)
 
@@ -391,20 +391,20 @@ class matrix(object):
 
     def trace(self, axis=None):
         return self._aggFn('trace', axis)
-        
+
     def _aggFn(self, fnName, axis):
         """
         Common function that is called for functions that have axis as parameter.
-        """ 
+        """
         dmlOp = DMLOp([self])
         out = matrix(None, op=dmlOp)
         if axis is None:
             dmlOp.dml = [out.ID, ' = ', fnName, '(', self.ID, ')\n']
         else:
             dmlOp.dml = [out.ID, ' = ', fnName, '(', self.ID, ', axis=', str(axis) ,')\n']
-        return out        
+        return out
 
     def dot(self, other):
         return binaryMatrixFunction(self, other, 'dot')
-            
-__all__ = [ 'setSparkContext', 'matrix', 'eval', 'solve']
\ No newline at end of file
+
+__all__ = [ 'setSparkContext', 'matrix', 'eval', 'solve']

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/10e701de/src/main/python/SystemML/mlcontext.py
----------------------------------------------------------------------
diff --git a/src/main/python/SystemML/mlcontext.py b/src/main/python/SystemML/mlcontext.py
index 7ed277a..1b90e70 100644
--- a/src/main/python/SystemML/mlcontext.py
+++ b/src/main/python/SystemML/mlcontext.py
@@ -22,10 +22,11 @@
 import os
 
 try:
+    import py4j.java_gateway
     from py4j.java_gateway import JavaObject
 except ImportError:
     raise ImportError('Unable to import JavaObject from py4j.java_gateway. Hint: Make sure you are running with pyspark')
-    
+
 from pyspark import SparkContext
 import pyspark.mllib.common
 from pyspark.sql import DataFrame, SQLContext
@@ -34,12 +35,12 @@ from .converters import *
 def dml(scriptString):
     """
     Create a dml script object based on a string.
-    
+
     Parameters
     ----------
     scriptString: string
         Can be a path to a dml script or a dml script itself.
-        
+
     Returns
     -------
     script: Script instance
@@ -53,12 +54,12 @@ def dml(scriptString):
 def pydml(scriptString):
     """
     Create a pydml script object based on a string.
-    
+
     Parameters
     ----------
     scriptString: string
         Can be a path to a pydml script or a pydml script itself.
-        
+
     Returns
     -------
     script: Script instance
@@ -92,12 +93,12 @@ def _py2java(sc, obj):
 class Matrix(object):
     """
     Wrapper around a Java Matrix object.
-    
+
     Parameters
     ----------
     javaMatrix: JavaObject
         A Java Matrix object as returned by calling `ml.execute().get()`.
-        
+
     sc: SparkContext
         SparkContext
     """
@@ -111,7 +112,7 @@ class Matrix(object):
     def toDF(self):
         """
         Convert the Matrix to a PySpark SQL DataFrame.
-        
+
         Returns
         -------
         df: PySpark SQL DataFrame
@@ -128,12 +129,12 @@ class Matrix(object):
 class MLResults(object):
     """
     Wrapper around a Java ML Results object.
-    
+
     Parameters
     ----------
     results: JavaObject
         A Java MLResults object as returned by calling `ml.execute()`.
-        
+
     sc: SparkContext
         SparkContext
     """
@@ -160,7 +161,7 @@ class MLResults(object):
         if len(outs) == 1:
             return outs[0]
         return outs
-    
+
     def getDataFrame(self, *outputs):
         """
         Parameters
@@ -172,7 +173,7 @@ class MLResults(object):
         if len(outs) == 1:
             return outs[0]
         return outs
-            
+
     def get(self, *outputs):
         """
         Parameters
@@ -194,7 +195,7 @@ class Script(object):
     ----------
     scriptString: string
         Can be either a file path to a DML script or a DML script itself.
-    
+
     scriptType: string
         Script language, either "dml" for DML (R-like) or "pydml" for PyDML (Python-like).
     """
@@ -223,7 +224,7 @@ class Script(object):
             self._input[name] = value
         return self
 
-    def out(self, *names):
+    def output(self, *names):
         """
         Parameters
         ----------
@@ -287,10 +288,15 @@ class MLContext(object):
                 script_java = self._sc._jvm.org.apache.sysml.api.mlcontext.ScriptFactory.pydml(scriptString)
 
         for key, val in script._input.items():
-            script_java.input(key, _py2java(self._sc, val))
+            # `in` is a reserved word ("keyword") in Python, so `script_java.in(...)` is not
+            # allowed. Therefore, we use the following code in which we retrieve a function
+            # representing `script_java.in`, and then call it with the arguments.  This is in
+            # lieu of adding a new `input` method on the JVM side, as that would complicate use
+            # from Scala/Java.
+            py4j.java_gateway.get_method(script_java, "in")(key, _py2java(self._sc, val))
         for val in script._output:
             script_java.out(val)
         return MLResults(self._ml.execute(script_java), self._sc)
 
 
-__all__ = ['MLResults', 'MLContext', 'Script', 'dml', 'pydml']
\ No newline at end of file
+__all__ = ['MLResults', 'MLContext', 'Script', 'dml', 'pydml']

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/10e701de/src/main/python/tests/test_mlcontext.py
----------------------------------------------------------------------
diff --git a/src/main/python/tests/test_mlcontext.py b/src/main/python/tests/test_mlcontext.py
index ec5a196..182a4d8 100644
--- a/src/main/python/tests/test_mlcontext.py
+++ b/src/main/python/tests/test_mlcontext.py
@@ -31,7 +31,7 @@ ml = MLContext(sc)
 class TestAPI(unittest.TestCase):
 
     def test_output_string(self):
-        script = dml("x1 = 'Hello World'").out("x1")
+        script = dml("x1 = 'Hello World'").output("x1")
         self.assertEqual(ml.execute(script).get("x1"), "Hello World")
 
     def test_output_list(self):
@@ -40,7 +40,7 @@ class TestAPI(unittest.TestCase):
         x2 = x1 + 1
         x3 = x1 + 2
         """
-        script = dml(script).out("x1", "x2", "x3")
+        script = dml(script).output("x1", "x2", "x3")
         self.assertEqual(ml.execute(script).get("x1", "x2"), [0.2, 1.2])
         self.assertEqual(ml.execute(script).get("x1", "x3"), [0.2, 2.2])
 
@@ -50,7 +50,7 @@ class TestAPI(unittest.TestCase):
         m2 = m1 * 2
         """
         rdd1 = sc.parallelize(["1.0,2.0", "3.0,4.0"])
-        script = dml(sums).input(m1=rdd1).out("s1", "m2")
+        script = dml(sums).input(m1=rdd1).output("s1", "m2")
         s1, m2 = ml.execute(script).get("s1", "m2")
         self.assertEqual((s1, repr(m2)), (10.0, "Matrix"))
 
@@ -60,7 +60,7 @@ class TestAPI(unittest.TestCase):
         m2 = m1 * 2
         """
         rdd1 = sc.parallelize(["1.0,2.0", "3.0,4.0"])
-        script = dml(sums).input(m1=rdd1).out("m2")
+        script = dml(sums).input(m1=rdd1).output("m2")
         m2 = ml.execute(script).get("m2")
         self.assertEqual(repr(m2.toDF()), "DataFrame[ID: double, C1: double, C2: double]")
 
@@ -69,14 +69,14 @@ class TestAPI(unittest.TestCase):
         x2 = x1 + 1
         x3 = x1 + 2
         """
-        script = dml(script).input("x1", 5).out("x2", "x3")
+        script = dml(script).input("x1", 5).output("x2", "x3")
         self.assertEqual(ml.execute(script).get("x2", "x3"), [6, 7])
 
     def test_input(self):
         script = """
         x3 = x1 + x2
         """
-        script = dml(script).input(x1=5, x2=3).out("x3")
+        script = dml(script).input(x1=5, x2=3).output("x3")
         self.assertEqual(ml.execute(script).get("x3"), 8)
 
     def test_rdd(self):
@@ -87,13 +87,13 @@ class TestAPI(unittest.TestCase):
         """
         rdd1 = sc.parallelize(["1.0,2.0", "3.0,4.0"])
         rdd2 = sc.parallelize(["5.0,6.0", "7.0,8.0"])
-        script = dml(sums).input(m1=rdd1).input(m2=rdd2).out("s1", "s2", "s3")
+        script = dml(sums).input(m1=rdd1).input(m2=rdd2).output("s1", "s2", "s3")
         self.assertEqual(
             ml.execute(script).get("s1", "s2", "s3"), [10.0, 26.0, "whatever"])
 
     def test_pydml(self):
         script = "A = full('1 2 3 4 5 6 7 8 9', rows=3, cols=3)\nx = toString(A)"
-        script = pydml(script).out("x")
+        script = pydml(script).output("x")
         self.assertEqual(
             ml.execute(script).get("x"),
             '1.000 2.000 3.000\n4.000 5.000 6.000\n7.000 8.000 9.000\n'
@@ -101,4 +101,4 @@ class TestAPI(unittest.TestCase):
 
 
 if __name__ == "__main__":
-    unittest.main()
\ No newline at end of file
+    unittest.main()