From 88eff98ba6935c2805a34e37482de7344b3b2b7c Mon Sep 17 00:00:00 2001 From: shivsood Date: Wed, 3 Apr 2019 14:28:41 -0700 Subject: [PATCH 1/3] spark samples v1 --- .../spark/hello_PySpark.ipynb | 36 ++++ .../spark/hello_Scala.ipynb | 49 ++++++ .../spark/hello_sparkR.ipynb | 31 ++++ .../spark/spark_to_sql_jdbc.ipynb | 78 +++++++++ ...in_score_export_ml_models_with_spark.ipynb | 160 ++++++++++++++++++ 5 files changed, 354 insertions(+) create mode 100644 samples/features/sql-big-data-cluster/spark/hello_PySpark.ipynb create mode 100644 samples/features/sql-big-data-cluster/spark/hello_Scala.ipynb create mode 100644 samples/features/sql-big-data-cluster/spark/hello_sparkR.ipynb create mode 100644 samples/features/sql-big-data-cluster/spark/spark_to_sql_jdbc.ipynb create mode 100644 samples/features/sql-big-data-cluster/spark/train_score_export_ml_models_with_spark.ipynb diff --git a/samples/features/sql-big-data-cluster/spark/hello_PySpark.ipynb b/samples/features/sql-big-data-cluster/spark/hello_PySpark.ipynb new file mode 100644 index 00000000..30412807 --- /dev/null +++ b/samples/features/sql-big-data-cluster/spark/hello_PySpark.ipynb @@ -0,0 +1,36 @@ +{ + "metadata": { + "kernelspec": { + "name": "pyspark3kernel", + "display_name": "PySpark3" + }, + "language_info": { + "name": "pyspark3", + "mimetype": "text/x-python", + "codemirror_mode": { + "name": "python", + "version": 3 + }, + "pygments_lexer": "python3" + } + }, + "nbformat_minor": 2, + "nbformat": 4, + "cells": [ + { + "cell_type": "code", + "source": "print(\"Hello World! \")\r\n\r\nimport sys\r\nprint(\"Python version \",sys.version)\r\n\r\n#Run some python in notebook\r\nnum = [i*i for i in range(0,20)]\r\nprint(\"My squared numbers \", num)\r\n", + "metadata": { + "language": "python" + }, + "outputs": [ + { + "name": "stdout", + "text": "Hello World! \nPython version 3.5.2 (default, Nov 12 2018, 13:43:14) \n[GCC 5.4.0 20160609]\nMy squared numbers [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361]", + "output_type": "stream" + } + ], + "execution_count": 1 + } + ] +} \ No newline at end of file diff --git a/samples/features/sql-big-data-cluster/spark/hello_Scala.ipynb b/samples/features/sql-big-data-cluster/spark/hello_Scala.ipynb new file mode 100644 index 00000000..2ae643b9 --- /dev/null +++ b/samples/features/sql-big-data-cluster/spark/hello_Scala.ipynb @@ -0,0 +1,49 @@ +{ + "metadata": { + "kernelspec": { + "name": "sparkkernel", + "display_name": "Spark | Scala" + }, + "language_info": { + "name": "scala", + "mimetype": "text/x-scala", + "codemirror_mode": "text/x-scala", + "pygments_lexer": "scala" + } + }, + "nbformat_minor": 2, + "nbformat": 4, + "cells": [ + { + "cell_type": "code", + "source": "object HelloWorld {\r\n def main(args: Array[String]): Unit= { println(\"Hello Spark Scala\")\r\n }\r\n}\r\n", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "text": "Starting Spark application\n", + "output_type": "stream" + }, + { + "data": { + "text/plain": "", + "text/html": "\n
IDYARN Application IDKindStateSpark UIDriver logCurrent session?
3application_1554316083160_0004sparkidleLinkLink
" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "text": "SparkSession available as 'spark'.\n", + "output_type": "stream" + }, + { + "name": "stdout", + "text": "defined object HelloWorld\n", + "output_type": "stream" + } + ], + "execution_count": 2 + } + ] +} \ No newline at end of file diff --git a/samples/features/sql-big-data-cluster/spark/hello_sparkR.ipynb b/samples/features/sql-big-data-cluster/spark/hello_sparkR.ipynb new file mode 100644 index 00000000..2cf4e00a --- /dev/null +++ b/samples/features/sql-big-data-cluster/spark/hello_sparkR.ipynb @@ -0,0 +1,31 @@ +{ + "metadata": { + "kernelspec": { + "name": "sparkrkernel", + "display_name": "Spark | R" + }, + "language_info": { + "name": "sparkR", + "mimetype": "text/x-rsrc", + "codemirror_mode": "text/x-rsrc", + "pygments_lexer": "r" + } + }, + "nbformat_minor": 2, + "nbformat": 4, + "cells": [ + { + "cell_type": "code", + "source": "print(\"Hello SparkR\")\r\n\r\nhead(iris)\r\n", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "text": "[1] \"Hello SparkR\"\n Sepal.Length Sepal.Width Petal.Length Petal.Width Species\n1 5.1 3.5 1.4 0.2 setosa\n2 4.9 3.0 1.4 0.2 setosa\n3 4.7 3.2 1.3 0.2 setosa\n4 4.6 3.1 1.5 0.2 setosa\n5 5.0 3.6 1.4 0.2 setosa\n6 5.4 3.9 1.7 0.4 setosa", + "output_type": "stream" + } + ], + "execution_count": 5 + } + ] +} \ No newline at end of file diff --git a/samples/features/sql-big-data-cluster/spark/spark_to_sql_jdbc.ipynb b/samples/features/sql-big-data-cluster/spark/spark_to_sql_jdbc.ipynb new file mode 100644 index 00000000..e06f7876 --- /dev/null +++ b/samples/features/sql-big-data-cluster/spark/spark_to_sql_jdbc.ipynb @@ -0,0 +1,78 @@ +{ + "metadata": { + "kernelspec": { + "name": "pyspark3kernel", + "display_name": "PySpark3" + }, + "language_info": { + "name": "pyspark3", + "mimetype": "text/x-python", + "codemirror_mode": { + "name": "python", + "version": 3 + }, + "pygments_lexer": "python3" + } + }, + "nbformat_minor": 2, + "nbformat": 4, + "cells": [ + { + "cell_type": "markdown", + "source": "# Read and write from Spark to SQL\r\nA typical big data scenario is large scale ETL in Spark and writing the processed data to SQLServer. The following samples shows \r\n- reading a HDFS file, \r\n- some basic processing on it and \r\n- then processed data to SQL Server table.\r\n\r\nNeed a database precreated in SQL for this sample. Here we are using database name \"MyTestDatabase\" that can be created using SQL statements below.\r\n\r\n``` sql\r\nCreate DATABASE MyTestDatabase\r\nGO \r\n``` \r\n ", + "metadata": {} + }, + { + "cell_type": "code", + "source": "\r\n#Read a file and then write it to the SQL table\r\ndatafile = \"/spark_data/AdultCensusIncome.csv\"\r\ndf = spark.read.format('csv').options(header='true', inferSchema='true', ignoreLeadingWhiteSpace='true', ignoreTrailingWhiteSpace='true').load(datafile)\r\ndf.show(5)\r\n", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "text": "+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n|age| workclass|fnlwgt|education|education-num| marital-status| occupation| relationship| race| sex|capital-gain|capital-loss|hours-per-week|native-country|income|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n| 39| State-gov| 77516|Bachelors| 13| Never-married| Adm-clerical|Not-in-family|White| Male| 2174| 0| 40| United-States| <=50K|\n| 50|Self-emp-not-inc| 83311|Bachelors| 13|Married-civ-spouse| Exec-managerial| Husband|White| Male| 0| 0| 13| United-States| <=50K|\n| 38| Private|215646| HS-grad| 9| Divorced|Handlers-cleaners|Not-in-family|White| Male| 0| 0| 40| United-States| <=50K|\n| 53| Private|234721| 11th| 7|Married-civ-spouse|Handlers-cleaners| Husband|Black| Male| 0| 0| 40| United-States| <=50K|\n| 28| Private|338409|Bachelors| 13|Married-civ-spouse| Prof-specialty| Wife|Black|Female| 0| 0| 40| Cuba| <=50K|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\nonly showing top 5 rows", + "output_type": "stream" + } + ], + "execution_count": 8 + }, + { + "cell_type": "code", + "source": "\r\n#Process this data. Very simple data cleanup steps. Replacing \"-\" with \"_\" in column names\r\ncolumns_new = [col.replace(\"-\", \"_\") for col in df.columns]\r\ndf = df.toDF(*columns_new)\r\ndf.show(5)\r\n\r\n", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "text": "+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n|age| workclass|fnlwgt|education|education_num| marital_status| occupation| relationship| race| sex|capital_gain|capital_loss|hours_per_week|native_country|income|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n| 39| State-gov| 77516|Bachelors| 13| Never-married| Adm-clerical|Not-in-family|White| Male| 2174| 0| 40| United-States| <=50K|\n| 50|Self-emp-not-inc| 83311|Bachelors| 13|Married-civ-spouse| Exec-managerial| Husband|White| Male| 0| 0| 13| United-States| <=50K|\n| 38| Private|215646| HS-grad| 9| Divorced|Handlers-cleaners|Not-in-family|White| Male| 0| 0| 40| United-States| <=50K|\n| 53| Private|234721| 11th| 7|Married-civ-spouse|Handlers-cleaners| Husband|Black| Male| 0| 0| 40| United-States| <=50K|\n| 28| Private|338409|Bachelors| 13|Married-civ-spouse| Prof-specialty| Wife|Black|Female| 0| 0| 40| Cuba| <=50K|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\nonly showing top 5 rows", + "output_type": "stream" + } + ], + "execution_count": 9 + }, + { + "cell_type": "code", + "source": "#Write from Spark to SQL table using JDBC\r\nprint(\"Use build in JDBC connector to write to SQLServer master instance in Big data \")\r\n\r\nservername = \"jdbc:sqlserver://mssql-master-pool-0.service-master-pool\"\r\ndbname = \"MyTestDatabase\"\r\nurl = servername + \";\" + \"databaseName=\" + dbname + \";\"\r\n\r\nc = \"dbo.AdultCensus\"\r\nuser = \"sa\"\r\npassword = \"ShivTron007\"\r\n\r\nprint(\"url is \", url)\r\n\r\ntry:\r\n df.write \\\r\n .format(\"jdbc\") \\\r\n .mode(\"overwrite\") \\\r\n .option(\"url\", url) \\\r\n .option(\"dbtable\", dbtable) \\\r\n .option(\"user\", user) \\\r\n .option(\"password\", password)\\\r\n .save()\r\nexcept ValueError as error :\r\n print(\"JDBC Write failed\", error)\r\n\r\nprint(\"JDBC Write done \")\r\n\r\n\r\n", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "text": "Use build in JDBC connector to write to SQLServer master instance in Big data \nurl is jdbc:sqlserver://mssql-master-pool-0.service-master-pool;databaseName=MyTestDatabase;\nJDBC Write done", + "output_type": "stream" + } + ], + "execution_count": 10 + }, + { + "cell_type": "code", + "source": "#Read to Spark from SQL table using JDBC\r\nprint(\"read data from SQL server table \")\r\njdbcDF = spark.read \\\r\n .format(\"jdbc\") \\\r\n .option(\"url\", url\r\n ) \\\r\n .option(\"dbtable\", dbtable) \\\r\n .option(\"user\", user) \\\r\n .option(\"password\", password) \\\r\n .load()\r\n\r\njdbcDF.show(5)", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "text": "read data from SQL server table \n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n|age| workclass|fnlwgt|education|education_num| marital_status| occupation| relationship| race| sex|capital_gain|capital_loss|hours_per_week|native_country|income|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n| 39| State-gov| 77516|Bachelors| 13| Never-married| Adm-clerical|Not-in-family|White| Male| 2174| 0| 40| United-States| <=50K|\n| 50|Self-emp-not-inc| 83311|Bachelors| 13|Married-civ-spouse| Exec-managerial| Husband|White| Male| 0| 0| 13| United-States| <=50K|\n| 38| Private|215646| HS-grad| 9| Divorced|Handlers-cleaners|Not-in-family|White| Male| 0| 0| 40| United-States| <=50K|\n| 53| Private|234721| 11th| 7|Married-civ-spouse|Handlers-cleaners| Husband|Black| Male| 0| 0| 40| United-States| <=50K|\n| 28| Private|338409|Bachelors| 13|Married-civ-spouse| Prof-specialty| Wife|Black|Female| 0| 0| 40| Cuba| <=50K|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\nonly showing top 5 rows", + "output_type": "stream" + } + ], + "execution_count": 13 + } + ] +} \ No newline at end of file diff --git a/samples/features/sql-big-data-cluster/spark/train_score_export_ml_models_with_spark.ipynb b/samples/features/sql-big-data-cluster/spark/train_score_export_ml_models_with_spark.ipynb new file mode 100644 index 00000000..2d0d5bc7 --- /dev/null +++ b/samples/features/sql-big-data-cluster/spark/train_score_export_ml_models_with_spark.ipynb @@ -0,0 +1,160 @@ +{ + "metadata": { + "kernelspec": { + "name": "pyspark3kernel", + "display_name": "PySpark3" + }, + "language_info": { + "name": "pyspark3", + "mimetype": "text/x-python", + "codemirror_mode": { + "name": "python", + "version": 3 + }, + "pygments_lexer": "python3" + } + }, + "nbformat_minor": 2, + "nbformat": 4, + "cells": [ + { + "cell_type": "markdown", + "source": "# Machine learning with SPARK in SQL Server 2019 Big Data Cluster\r\nSpark in Unified Big data compute engine that enables big data processing, Machine learning and AI\r\n\r\nKey Spark advantages are \r\n1. Distributed compute enging \r\n2. Choice of langauge (Python, R, Scala, Java)\r\n3. Single engine for Batch and Streaming jobs\r\n\r\nIn this tutorial we'll cover how we can use Spark to create and deploy machine learning models. The example is a python(PySpark) sample. The same can also be done using Scala and R ( SparkR) in Spark.\r\n\r\n\"drawing\"\r\n\r\n## Steps\r\n1. Explore your Data\r\n2. Data Prep and split Data as Training and Test set\r\n3. Model Training\r\n4. Model Scoring \r\n5. Persist as Spark Model\r\n6. Persist as Portable Model\r\n\r\nE2E machine learning involves several additional step e.g data exploration, feature selection and principal component analysis,model selection etc. Many of these steps are ignored here for brevity.\r\n\r\n\r\n\r\n", + "metadata": {} + }, + { + "cell_type": "markdown", + "source": "## Step 1 - Explore your data\r\n### Load the data\r\nFor this example we'll use **AdultCensusIncome** data from [here]( https://amldockerdatasets.azureedge.net/AdultCensusIncome.csv ). From your Azure Data Studio connect to the HDFS/Spark gateway and create a directory called spark_ml under HDFS. \r\nDownload [AdultCensusIncome.csv]( https://amldockerdatasets.azureedge.net/AdultCensusIncome.csv ) to your local machine and upload to HDFS.Upload AdultCensusIncome.csv to the folder we created.\r\n\r\n### Exploratory Analysis\r\n- Baisc exploration on the data\r\n- Labels & Features\r\n1. **Label** - This refers to predicted value. This is represented as a column in the data. Label is **income** \r\n2. **Features** - This refers to the characteristics that are used to predict. **age** and **hours_per_week**\r\n\r\nNote : In reality features are chosen by applying some correlations techniques to understand what best characterize the Label we are predicting.\r\n\r\n### The Model we will build\r\nIn AdultCensusIncome.csv contains several columsn like Income range, age, hours-per-week, education, occupation etc. We'll build a model that can predict income range would be >50K or <50K.\r\n", + "metadata": {} + }, + { + "cell_type": "code", + "source": "datafile = \"/spark_data/AdultCensusIncome.csv\"\r\n\r\n#Read the data to a spark data frame.\r\ndata_all = spark.read.format('csv').options(header='true', inferSchema='true', ignoreLeadingWhiteSpace='true', ignoreTrailingWhiteSpace='true').load(datafile)\r\nprint(\"Number of rows: {}, Number of coulumns : {}\".format(data_all.count(), len(data_all.columns)))\r\ndata_all.printSchema() \r\n\r\n#Replace \"-\" with \"_\" in column names\r\ncolumns_new = [col.replace(\"-\", \"_\") for col in data_all.columns]\r\ndata_all = data_all.toDF(*columns_new)\r\ndata_all.printSchema()\r\n", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "text": "Number of rows: 32561, Number of coulumns : 15\nroot\n |-- age: integer (nullable = true)\n |-- workclass: string (nullable = true)\n |-- fnlwgt: integer (nullable = true)\n |-- education: string (nullable = true)\n |-- education-num: integer (nullable = true)\n |-- marital-status: string (nullable = true)\n |-- occupation: string (nullable = true)\n |-- relationship: string (nullable = true)\n |-- race: string (nullable = true)\n |-- sex: string (nullable = true)\n |-- capital-gain: integer (nullable = true)\n |-- capital-loss: integer (nullable = true)\n |-- hours-per-week: integer (nullable = true)\n |-- native-country: string (nullable = true)\n |-- income: string (nullable = true)\n\nroot\n |-- age: integer (nullable = true)\n |-- workclass: string (nullable = true)\n |-- fnlwgt: integer (nullable = true)\n |-- education: string (nullable = true)\n |-- education_num: integer (nullable = true)\n |-- marital_status: string (nullable = true)\n |-- occupation: string (nullable = true)\n |-- relationship: string (nullable = true)\n |-- race: string (nullable = true)\n |-- sex: string (nullable = true)\n |-- capital_gain: integer (nullable = true)\n |-- capital_loss: integer (nullable = true)\n |-- hours_per_week: integer (nullable = true)\n |-- native_country: string (nullable = true)\n |-- income: string (nullable = true)", + "output_type": "stream" + } + ], + "execution_count": 3 + }, + { + "cell_type": "code", + "source": "#Basic data exploration\r\n\r\n##1. Sub set the data and print some important columns\r\nprint(\"Select few columns to see the data\")\r\ndata_all.select(['income','age','hours_per_week']).show(10)\r\n\r\n## Find the number of distict values\r\nprint(\"Number of distinct values for income\")\r\nds_sub = data_all.select('income').distinct()\r\nds_sub.show()\r\n\r\n##Add a numberic column(income_code) derived from income column\r\nprint(\"Added numeric column(income_code) derived from income column\")\r\nfrom pyspark.sql.functions import expr\r\n\r\ndf_new = data_all.withColumn(\"income_code\", expr(\"case \\\r\n when income like '%<=50K%' then 0 \\\r\n when income like '%>50K%' then 1 \\\r\n else 2 end \"))\r\n\r\ndf_new.select(['income','age','hours_per_week','income_code']).show(10)\r\n\r\n##Summary statistical operations on dataframe\r\nprint(\"Print a statistical summary of a few columns\")\r\ndf_new.select(['income','age','hours_per_week','income_code']).describe().show()\r\n\r\nprint(\"Calculate Co variance between a few columns to understand features to use\")\r\nmycov = df_new.stat.cov('income_code','hours_per_week')\r\nprint(\"Covariance between income and hours_per_week is\", round(mycov,1))\r\n\r\nmycov = df_new.stat.cov('income_code','age')\r\nprint(\"Covariance between income and age is\", round(mycov,1))\r\n\r\n", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "text": "Select few columns to see the data\n+------+---+--------------+\n|income|age|hours_per_week|\n+------+---+--------------+\n| <=50K| 39| 40|\n| <=50K| 50| 13|\n| <=50K| 38| 40|\n| <=50K| 53| 40|\n| <=50K| 28| 40|\n| <=50K| 37| 40|\n| <=50K| 49| 16|\n| >50K| 52| 45|\n| >50K| 31| 50|\n| >50K| 42| 40|\n+------+---+--------------+\nonly showing top 10 rows\n\nNumber of distinct values for income\n+------+\n|income|\n+------+\n| <=50K|\n| >50K|\n+------+\n\nAdded numeric column(income_code) derived from income column\n+------+---+--------------+-----------+\n|income|age|hours_per_week|income_code|\n+------+---+--------------+-----------+\n| <=50K| 39| 40| 0|\n| <=50K| 50| 13| 0|\n| <=50K| 38| 40| 0|\n| <=50K| 53| 40| 0|\n| <=50K| 28| 40| 0|\n| <=50K| 37| 40| 0|\n| <=50K| 49| 16| 0|\n| >50K| 52| 45| 1|\n| >50K| 31| 50| 1|\n| >50K| 42| 40| 1|\n+------+---+--------------+-----------+\nonly showing top 10 rows\n\nPrint a statistical summary of a few columns\n+-------+------+------------------+------------------+-------------------+\n|summary|income| age| hours_per_week| income_code|\n+-------+------+------------------+------------------+-------------------+\n| count| 32561| 32561| 32561| 32561|\n| mean| null| 38.58164675532078|40.437455852092995| 0.2408095574460244|\n| stddev| null|13.640432553581356|12.347428681731838|0.42758148856469247|\n| min| <=50K| 17| 1| 0|\n| max| >50K| 90| 99| 1|\n+-------+------+------------------+------------------+-------------------+\n\nCalculate Co variance between a few columns to understand features to use\nCovariance between income and hours_per_week is 1.2\nCovariance between income and age is 1.4", + "output_type": "stream" + } + ], + "execution_count": 4 + }, + { + "cell_type": "code", + "source": "# Choose feature columns and the label column.\r\nlabel = \"income\"\r\nxvars = [\"age\", \"hours_per_week\"] #all numeric\r\n\r\nprint(\"label = {}\".format(label))\r\nprint(\"features = {}\".format(xvars))\r\n\r\n#Check label counts to check data bias\r\nprint(\"Count of rows that are <=50K\", data_all[data_all.income==\"<=50K\"].count())\r\nprint(\"Count of rows that are >50K\", data_all[data_all.income==\">50K\"].count())\r\n\r\n\r\nselect_cols = xvars\r\nselect_cols.append(label)\r\ndata = data_all.select(select_cols)", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "text": "label = income\nfeatures = ['age', 'hours_per_week']\nCount of rows that are <=50K 24720\nCount of rows that are >50K 7841", + "output_type": "stream" + } + ], + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": "## Step 2 - Split as training and test set\r\nWe'll use 75% of rows to train the model and rest of the 25% to evaluate the model. Additionally we persist the train and test data sets to HDFS storage. The step is not necessary , but shown to demonstrate saving and loading with ORC format. Other format e.g. Parquet may also be used. Post this step you should see 2 directories created with the name \"AdultCensusIncomeTrain\" and \"AdultCensusIncomeTest\"\r\n", + "metadata": {} + }, + { + "cell_type": "code", + "source": "train, test = data.randomSplit([0.75, 0.25], seed=123)\r\n\r\nprint(\"train ({}, {})\".format(train.count(), len(train.columns)))\r\nprint(\"test ({}, {})\".format(test.count(), len(test.columns)))\r\n\r\ntrain_data_path = \"/spark_ml/AdultCensusIncomeTrain\"\r\ntest_data_path = \"/spark_ml/AdultCensusIncomeTest\"\r\n\r\ntrain.write.mode('overwrite').orc(train_data_path)\r\ntest.write.mode('overwrite').orc(test_data_path)\r\nprint(\"train and test datasets saved to {} and {}\".format(train_data_path, test_data_path))", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "text": "train (24469, 3)\ntest (8092, 3)\ntrain and test datasets saved to /spark_ml/AdultCensusIncomeTrain and /spark_ml/AdultCensusIncomeTest", + "output_type": "stream" + } + ], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": "## Step 3 - Train a model\r\n[Spark ML pipeline] ( https://spark.apache.org/docs/2.3.1/ml-pipeline.html ) allow to sequence all steps as a workflow and make it easier to experiment with various algorithms and their parameters. The following code first constructs the stages and then puts these stages together in Ml pipeline. LogisticRegression is used to create the model.\r\n\r\n", + "metadata": {} + }, + { + "cell_type": "code", + "source": "from pyspark.ml import Pipeline, PipelineModel\r\nfrom pyspark.ml.feature import OneHotEncoder, StringIndexer, VectorAssembler\r\nfrom pyspark.ml.classification import LogisticRegression\r\n\r\nreg = 0.1\r\nprint(\"Using LogisticRegression model with Regularization Rate of {}.\".format(reg))\r\n\r\n# create a new Logistic Regression model.\r\nlr = LogisticRegression(regParam=reg)\r\n\r\ndtypes = dict(train.dtypes)\r\ndtypes.pop(label)\r\n\r\nsi_xvars = []\r\nohe_xvars = []\r\nfeatureCols = []\r\nfor idx,key in enumerate(dtypes):\r\n if dtypes[key] == \"string\":\r\n featureCol = \"-\".join([key, \"encoded\"])\r\n featureCols.append(featureCol)\r\n \r\n tmpCol = \"-\".join([key, \"tmp\"])\r\n si_xvars.append(StringIndexer(inputCol=key, outputCol=tmpCol, handleInvalid=\"skip\")) #, handleInvalid=\"keep\"\r\n ohe_xvars.append(OneHotEncoder(inputCol=tmpCol, outputCol=featureCol))\r\n else:\r\n featureCols.append(key)\r\n\r\n# string-index the label column into a column named \"label\"\r\nsi_label = StringIndexer(inputCol=label, outputCol='label')\r\n\r\n# assemble the encoded feature columns in to a column named \"features\"\r\nassembler = VectorAssembler(inputCols=featureCols, outputCol=\"features\")\r\n\r\n\r\nstages = []\r\nstages.extend(si_xvars)\r\nstages.extend(ohe_xvars)\r\nstages.append(si_label)\r\nstages.append(assembler)\r\nstages.append(lr)\r\npipe = Pipeline(stages=stages)\r\nprint(\"Pipeline Created\")\r\n\r\nmodel = pipe.fit(train)\r\nprint(\"Model Trained\")\r\nprint(\"Model is \", model)\r\nprint(\"Model Stages\", model.stages)", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "text": "Using LogisticRegression model with Regularization Rate of 0.1.\nPipeline Created\nModel Trained\nModel is PipelineModel_e5284bc61285\nModel Stages [StringIndexer_1ecf86c8d2ae, VectorAssembler_450ee37e6955, LogisticRegressionModel: uid = LogisticRegression_deb52c17940d, numClasses = 2, numFeatures = 2]", + "output_type": "stream" + } + ], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": "## Step 4 - Model scoring\r\n\r\nPredict using the model and Evaluate the model accuracy\r\n \r\nThe code below use test data set to predict the outcome using the model created in the step above. We measure accuracy of the model with areaUnderROC and areaUnderPR metric.", + "metadata": {} + }, + { + "cell_type": "code", + "source": "from pyspark.ml.evaluation import BinaryClassificationEvaluator\r\n\r\n# make prediction\r\npred = model.transform(test)\r\n\r\n# evaluate. note only 2 metrics are supported out of the box by Spark ML.\r\nbce = BinaryClassificationEvaluator(rawPredictionCol='rawPrediction')\r\nau_roc = bce.setMetricName('areaUnderROC').evaluate(pred)\r\nau_prc = bce.setMetricName('areaUnderPR').evaluate(pred)\r\n\r\nprint(\"Area under ROC: {}\".format(au_roc))\r\nprint(\"Area Under PR: {}\".format(au_prc))\r\n\r\npred[pred.prediction==1.0][pred.income,pred.label,pred.prediction].show()", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "text": "Area under ROC: 0.7363559303440261\nArea Under PR: 0.39475773290351296\n+------+-----+----------+\n|income|label|prediction|\n+------+-----+----------+\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| >50K| 1.0| 1.0|\n| >50K| 1.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| >50K| 1.0| 1.0|\n| >50K| 1.0| 1.0|\n| <=50K| 0.0| 1.0|\n| >50K| 1.0| 1.0|\n| <=50K| 0.0| 1.0|\n| >50K| 1.0| 1.0|\n| <=50K| 0.0| 1.0|\n+------+-----+----------+\nonly showing top 20 rows", + "output_type": "stream" + } + ], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": "## Step 5 - Persist the Spark Models\r\nFinally we persist the model in HDFS for later use. Post this step the created model get saved as /spark_ml/AdultCensus.mml\r\n\r\n", + "metadata": {} + }, + { + "cell_type": "code", + "source": "model_name = \"AdultCensus.mml\"\r\nmodel_fs = \"/spark_ml/\" + model_name\r\n\r\nmodel.write().overwrite().save(model_fs)\r\nprint(\"saved model to {}\".format(model_fs))\r\n\r\n# load the model file and check its same as the in-memory model\r\nmodel2 = PipelineModel.load(model_fs)\r\nassert str(model2) == str(model)\r\nprint(\"Successfully loaded from {}\".format(model_fs))", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "text": "saved model to /spark_ml/AdultCensus.mml\nSuccessfully loaded from /spark_ml/AdultCensus.mml", + "output_type": "stream" + } + ], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "source": "## Step 6 - Persist as Portable Model\r\nHere we persist the Model in as Portable Mleap bundle for use outside Spark.", + "metadata": {} + }, + { + "cell_type": "code", + "source": "import os\r\nfrom mleap.pyspark.spark_support import SimpleSparkSerializer\r\n# serialize the model to a zip file in JSON format\r\nmodel_name_export = \"adult_census_pipeline.zip\"\r\nmodel_name_path = os.getcwd()\r\nmodel_file = os.path.join(model_name_path, model_name_export)\r\n\r\n# remove an old model file, if needed.\r\ntry:\r\n os.remove(model_file)\r\nexcept OSError:\r\n pass\r\n\r\nmodel_file_path = \"jar:file:{}\".format(model_file)\r\nmodel.serializeToBundle(model_file_path, model.transform(train))\r\n\r\nprint(\"persist the mleap bundle from local to hdfs\")\r\nfrom subprocess import Popen, PIPE\r\nproc = Popen([\"hadoop\", \"fs\", \"-put\", \"-f\", model_file, os.path.join(\"/spark_ml\", model_name_export)], stdout=PIPE, stderr=PIPE)\r\ns_output, s_err = proc.communicate()\r\n", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "text": "persist the mleap bundle from local to hdfs", + "output_type": "stream" + } + ], + "execution_count": 10 + } + ] +} \ No newline at end of file From f287c5e87adcd12057d8451c86e165479e60a952 Mon Sep 17 00:00:00 2001 From: shivsood Date: Fri, 5 Apr 2019 16:30:11 -0700 Subject: [PATCH 2/3] reorgs are essential to maintain sanity --- .../spark/{ => dataloading}/hello_PySpark.ipynb | 0 .../spark/{ => dataloading}/hello_Scala.ipynb | 0 .../spark/{ => dataloading}/hello_sparkR.ipynb | 0 .../sql-big-data-cluster/spark/{ => dataloading}/spark-sql.ipynb | 0 .../spark/{ => spark_to_sql}/spark_to_sql_jdbc.ipynb | 0 .../{ => sparkml}/train_score_export_ml_models_with_spark.ipynb | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename samples/features/sql-big-data-cluster/spark/{ => dataloading}/hello_PySpark.ipynb (100%) rename samples/features/sql-big-data-cluster/spark/{ => dataloading}/hello_Scala.ipynb (100%) rename samples/features/sql-big-data-cluster/spark/{ => dataloading}/hello_sparkR.ipynb (100%) rename samples/features/sql-big-data-cluster/spark/{ => dataloading}/spark-sql.ipynb (100%) rename samples/features/sql-big-data-cluster/spark/{ => spark_to_sql}/spark_to_sql_jdbc.ipynb (100%) rename samples/features/sql-big-data-cluster/spark/{ => sparkml}/train_score_export_ml_models_with_spark.ipynb (100%) diff --git a/samples/features/sql-big-data-cluster/spark/hello_PySpark.ipynb b/samples/features/sql-big-data-cluster/spark/dataloading/hello_PySpark.ipynb similarity index 100% rename from samples/features/sql-big-data-cluster/spark/hello_PySpark.ipynb rename to samples/features/sql-big-data-cluster/spark/dataloading/hello_PySpark.ipynb diff --git a/samples/features/sql-big-data-cluster/spark/hello_Scala.ipynb b/samples/features/sql-big-data-cluster/spark/dataloading/hello_Scala.ipynb similarity index 100% rename from samples/features/sql-big-data-cluster/spark/hello_Scala.ipynb rename to samples/features/sql-big-data-cluster/spark/dataloading/hello_Scala.ipynb diff --git a/samples/features/sql-big-data-cluster/spark/hello_sparkR.ipynb b/samples/features/sql-big-data-cluster/spark/dataloading/hello_sparkR.ipynb similarity index 100% rename from samples/features/sql-big-data-cluster/spark/hello_sparkR.ipynb rename to samples/features/sql-big-data-cluster/spark/dataloading/hello_sparkR.ipynb diff --git a/samples/features/sql-big-data-cluster/spark/spark-sql.ipynb b/samples/features/sql-big-data-cluster/spark/dataloading/spark-sql.ipynb similarity index 100% rename from samples/features/sql-big-data-cluster/spark/spark-sql.ipynb rename to samples/features/sql-big-data-cluster/spark/dataloading/spark-sql.ipynb diff --git a/samples/features/sql-big-data-cluster/spark/spark_to_sql_jdbc.ipynb b/samples/features/sql-big-data-cluster/spark/spark_to_sql/spark_to_sql_jdbc.ipynb similarity index 100% rename from samples/features/sql-big-data-cluster/spark/spark_to_sql_jdbc.ipynb rename to samples/features/sql-big-data-cluster/spark/spark_to_sql/spark_to_sql_jdbc.ipynb diff --git a/samples/features/sql-big-data-cluster/spark/train_score_export_ml_models_with_spark.ipynb b/samples/features/sql-big-data-cluster/spark/sparkml/train_score_export_ml_models_with_spark.ipynb similarity index 100% rename from samples/features/sql-big-data-cluster/spark/train_score_export_ml_models_with_spark.ipynb rename to samples/features/sql-big-data-cluster/spark/sparkml/train_score_export_ml_models_with_spark.ipynb From 191681558158114d01a3b9fb8ee8bd27b103a800 Mon Sep 17 00:00:00 2001 From: shivsood Date: Mon, 8 Apr 2019 16:40:02 -0700 Subject: [PATCH 3/3] add image file. Notebook does not still work with relative path for image --- .../spark_to_sql/spark_to_sql_jdbc.ipynb | 18 +++++----- .../sparkml/Train_Score_Export_with_Spark.jpg | Bin 0 -> 135628 bytes ...in_score_export_ml_models_with_spark.ipynb | 34 +++++++++--------- 3 files changed, 26 insertions(+), 26 deletions(-) create mode 100644 samples/features/sql-big-data-cluster/spark/sparkml/Train_Score_Export_with_Spark.jpg diff --git a/samples/features/sql-big-data-cluster/spark/spark_to_sql/spark_to_sql_jdbc.ipynb b/samples/features/sql-big-data-cluster/spark/spark_to_sql/spark_to_sql_jdbc.ipynb index e06f7876..0531f80d 100644 --- a/samples/features/sql-big-data-cluster/spark/spark_to_sql/spark_to_sql_jdbc.ipynb +++ b/samples/features/sql-big-data-cluster/spark/spark_to_sql/spark_to_sql_jdbc.ipynb @@ -28,9 +28,9 @@ "metadata": {}, "outputs": [ { + "output_type": "stream", "name": "stdout", - "text": "+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n|age| workclass|fnlwgt|education|education-num| marital-status| occupation| relationship| race| sex|capital-gain|capital-loss|hours-per-week|native-country|income|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n| 39| State-gov| 77516|Bachelors| 13| Never-married| Adm-clerical|Not-in-family|White| Male| 2174| 0| 40| United-States| <=50K|\n| 50|Self-emp-not-inc| 83311|Bachelors| 13|Married-civ-spouse| Exec-managerial| Husband|White| Male| 0| 0| 13| United-States| <=50K|\n| 38| Private|215646| HS-grad| 9| Divorced|Handlers-cleaners|Not-in-family|White| Male| 0| 0| 40| United-States| <=50K|\n| 53| Private|234721| 11th| 7|Married-civ-spouse|Handlers-cleaners| Husband|Black| Male| 0| 0| 40| United-States| <=50K|\n| 28| Private|338409|Bachelors| 13|Married-civ-spouse| Prof-specialty| Wife|Black|Female| 0| 0| 40| Cuba| <=50K|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\nonly showing top 5 rows", - "output_type": "stream" + "text": "+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n|age| workclass|fnlwgt|education|education-num| marital-status| occupation| relationship| race| sex|capital-gain|capital-loss|hours-per-week|native-country|income|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n| 39| State-gov| 77516|Bachelors| 13| Never-married| Adm-clerical|Not-in-family|White| Male| 2174| 0| 40| United-States| <=50K|\n| 50|Self-emp-not-inc| 83311|Bachelors| 13|Married-civ-spouse| Exec-managerial| Husband|White| Male| 0| 0| 13| United-States| <=50K|\n| 38| Private|215646| HS-grad| 9| Divorced|Handlers-cleaners|Not-in-family|White| Male| 0| 0| 40| United-States| <=50K|\n| 53| Private|234721| 11th| 7|Married-civ-spouse|Handlers-cleaners| Husband|Black| Male| 0| 0| 40| United-States| <=50K|\n| 28| Private|338409|Bachelors| 13|Married-civ-spouse| Prof-specialty| Wife|Black|Female| 0| 0| 40| Cuba| <=50K|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\nonly showing top 5 rows" } ], "execution_count": 8 @@ -41,22 +41,22 @@ "metadata": {}, "outputs": [ { + "output_type": "stream", "name": "stdout", - "text": "+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n|age| workclass|fnlwgt|education|education_num| marital_status| occupation| relationship| race| sex|capital_gain|capital_loss|hours_per_week|native_country|income|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n| 39| State-gov| 77516|Bachelors| 13| Never-married| Adm-clerical|Not-in-family|White| Male| 2174| 0| 40| United-States| <=50K|\n| 50|Self-emp-not-inc| 83311|Bachelors| 13|Married-civ-spouse| Exec-managerial| Husband|White| Male| 0| 0| 13| United-States| <=50K|\n| 38| Private|215646| HS-grad| 9| Divorced|Handlers-cleaners|Not-in-family|White| Male| 0| 0| 40| United-States| <=50K|\n| 53| Private|234721| 11th| 7|Married-civ-spouse|Handlers-cleaners| Husband|Black| Male| 0| 0| 40| United-States| <=50K|\n| 28| Private|338409|Bachelors| 13|Married-civ-spouse| Prof-specialty| Wife|Black|Female| 0| 0| 40| Cuba| <=50K|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\nonly showing top 5 rows", - "output_type": "stream" + "text": "+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n|age| workclass|fnlwgt|education|education_num| marital_status| occupation| relationship| race| sex|capital_gain|capital_loss|hours_per_week|native_country|income|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n| 39| State-gov| 77516|Bachelors| 13| Never-married| Adm-clerical|Not-in-family|White| Male| 2174| 0| 40| United-States| <=50K|\n| 50|Self-emp-not-inc| 83311|Bachelors| 13|Married-civ-spouse| Exec-managerial| Husband|White| Male| 0| 0| 13| United-States| <=50K|\n| 38| Private|215646| HS-grad| 9| Divorced|Handlers-cleaners|Not-in-family|White| Male| 0| 0| 40| United-States| <=50K|\n| 53| Private|234721| 11th| 7|Married-civ-spouse|Handlers-cleaners| Husband|Black| Male| 0| 0| 40| United-States| <=50K|\n| 28| Private|338409|Bachelors| 13|Married-civ-spouse| Prof-specialty| Wife|Black|Female| 0| 0| 40| Cuba| <=50K|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\nonly showing top 5 rows" } ], "execution_count": 9 }, { "cell_type": "code", - "source": "#Write from Spark to SQL table using JDBC\r\nprint(\"Use build in JDBC connector to write to SQLServer master instance in Big data \")\r\n\r\nservername = \"jdbc:sqlserver://mssql-master-pool-0.service-master-pool\"\r\ndbname = \"MyTestDatabase\"\r\nurl = servername + \";\" + \"databaseName=\" + dbname + \";\"\r\n\r\nc = \"dbo.AdultCensus\"\r\nuser = \"sa\"\r\npassword = \"ShivTron007\"\r\n\r\nprint(\"url is \", url)\r\n\r\ntry:\r\n df.write \\\r\n .format(\"jdbc\") \\\r\n .mode(\"overwrite\") \\\r\n .option(\"url\", url) \\\r\n .option(\"dbtable\", dbtable) \\\r\n .option(\"user\", user) \\\r\n .option(\"password\", password)\\\r\n .save()\r\nexcept ValueError as error :\r\n print(\"JDBC Write failed\", error)\r\n\r\nprint(\"JDBC Write done \")\r\n\r\n\r\n", + "source": "#Write from Spark to SQL table using JDBC\r\nprint(\"Use build in JDBC connector to write to SQLServer master instance in Big data \")\r\n\r\nservername = \"jdbc:sqlserver://mssql-master-pool-0.service-master-pool\"\r\ndbname = \"MyTestDatabase\"\r\nurl = servername + \";\" + \"databaseName=\" + dbname + \";\"\r\n\r\nc = \"dbo.AdultCensus\"\r\nuser = \"sa\"\r\npassword = \"****\"\r\n\r\nprint(\"url is \", url)\r\n\r\ntry:\r\n df.write \\\r\n .format(\"jdbc\") \\\r\n .mode(\"overwrite\") \\\r\n .option(\"url\", url) \\\r\n .option(\"dbtable\", dbtable) \\\r\n .option(\"user\", user) \\\r\n .option(\"password\", password)\\\r\n .save()\r\nexcept ValueError as error :\r\n print(\"JDBC Write failed\", error)\r\n\r\nprint(\"JDBC Write done \")\r\n\r\n\r\n", "metadata": {}, "outputs": [ { + "output_type": "stream", "name": "stdout", - "text": "Use build in JDBC connector to write to SQLServer master instance in Big data \nurl is jdbc:sqlserver://mssql-master-pool-0.service-master-pool;databaseName=MyTestDatabase;\nJDBC Write done", - "output_type": "stream" + "text": "Use build in JDBC connector to write to SQLServer master instance in Big data \nurl is jdbc:sqlserver://mssql-master-pool-0.service-master-pool;databaseName=MyTestDatabase;\nJDBC Write done" } ], "execution_count": 10 @@ -67,9 +67,9 @@ "metadata": {}, "outputs": [ { + "output_type": "stream", "name": "stdout", - "text": "read data from SQL server table \n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n|age| workclass|fnlwgt|education|education_num| marital_status| occupation| relationship| race| sex|capital_gain|capital_loss|hours_per_week|native_country|income|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n| 39| State-gov| 77516|Bachelors| 13| Never-married| Adm-clerical|Not-in-family|White| Male| 2174| 0| 40| United-States| <=50K|\n| 50|Self-emp-not-inc| 83311|Bachelors| 13|Married-civ-spouse| Exec-managerial| Husband|White| Male| 0| 0| 13| United-States| <=50K|\n| 38| Private|215646| HS-grad| 9| Divorced|Handlers-cleaners|Not-in-family|White| Male| 0| 0| 40| United-States| <=50K|\n| 53| Private|234721| 11th| 7|Married-civ-spouse|Handlers-cleaners| Husband|Black| Male| 0| 0| 40| United-States| <=50K|\n| 28| Private|338409|Bachelors| 13|Married-civ-spouse| Prof-specialty| Wife|Black|Female| 0| 0| 40| Cuba| <=50K|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\nonly showing top 5 rows", - "output_type": "stream" + "text": "read data from SQL server table \n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n|age| workclass|fnlwgt|education|education_num| marital_status| occupation| relationship| race| sex|capital_gain|capital_loss|hours_per_week|native_country|income|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\n| 39| State-gov| 77516|Bachelors| 13| Never-married| Adm-clerical|Not-in-family|White| Male| 2174| 0| 40| United-States| <=50K|\n| 50|Self-emp-not-inc| 83311|Bachelors| 13|Married-civ-spouse| Exec-managerial| Husband|White| Male| 0| 0| 13| United-States| <=50K|\n| 38| Private|215646| HS-grad| 9| Divorced|Handlers-cleaners|Not-in-family|White| Male| 0| 0| 40| United-States| <=50K|\n| 53| Private|234721| 11th| 7|Married-civ-spouse|Handlers-cleaners| Husband|Black| Male| 0| 0| 40| United-States| <=50K|\n| 28| Private|338409|Bachelors| 13|Married-civ-spouse| Prof-specialty| Wife|Black|Female| 0| 0| 40| Cuba| <=50K|\n+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+--------------+--------------+------+\nonly showing top 5 rows" } ], "execution_count": 13 diff --git a/samples/features/sql-big-data-cluster/spark/sparkml/Train_Score_Export_with_Spark.jpg b/samples/features/sql-big-data-cluster/spark/sparkml/Train_Score_Export_with_Spark.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0cc016f8a001ce83d4a5c64f8ee650eba991b7ce GIT binary patch literal 135628 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

~gMRY81P~M)4J;fU#%r#*MMbt~`GO_vo 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 literal 0 HcmV?d00001 diff --git a/samples/features/sql-big-data-cluster/spark/sparkml/train_score_export_ml_models_with_spark.ipynb b/samples/features/sql-big-data-cluster/spark/sparkml/train_score_export_ml_models_with_spark.ipynb index 2d0d5bc7..26567e6d 100644 --- a/samples/features/sql-big-data-cluster/spark/sparkml/train_score_export_ml_models_with_spark.ipynb +++ b/samples/features/sql-big-data-cluster/spark/sparkml/train_score_export_ml_models_with_spark.ipynb @@ -19,7 +19,7 @@ "cells": [ { "cell_type": "markdown", - "source": "# Machine learning with SPARK in SQL Server 2019 Big Data Cluster\r\nSpark in Unified Big data compute engine that enables big data processing, Machine learning and AI\r\n\r\nKey Spark advantages are \r\n1. Distributed compute enging \r\n2. Choice of langauge (Python, R, Scala, Java)\r\n3. Single engine for Batch and Streaming jobs\r\n\r\nIn this tutorial we'll cover how we can use Spark to create and deploy machine learning models. The example is a python(PySpark) sample. The same can also be done using Scala and R ( SparkR) in Spark.\r\n\r\n\"drawing\"\r\n\r\n## Steps\r\n1. Explore your Data\r\n2. Data Prep and split Data as Training and Test set\r\n3. Model Training\r\n4. Model Scoring \r\n5. Persist as Spark Model\r\n6. Persist as Portable Model\r\n\r\nE2E machine learning involves several additional step e.g data exploration, feature selection and principal component analysis,model selection etc. Many of these steps are ignored here for brevity.\r\n\r\n\r\n\r\n", + "source": "# Machine learning with SPARK in SQL Server 2019 Big Data Cluster\r\nSpark in Unified Big data compute engine that enables big data processing, Machine learning and AI\r\n\r\nKey Spark advantages are \r\n1. Distributed compute enging \r\n2. Choice of langauge (Python, R, Scala, Java)\r\n3. Single engine for Batch and Streaming jobs\r\n\r\nIn this tutorial we'll cover how we can use Spark to create and deploy machine learning models. The example is a python(PySpark) sample. The same can also be done using Scala and R ( SparkR) in Spark.\r\n\r\n\"drawing\"\r\n\r\n## Steps\r\n1. Explore your Data\r\n2. Data Prep and split Data as Training and Test set\r\n3. Model Training\r\n4. Model Scoring \r\n5. Persist as Spark Model\r\n6. Persist as Portable Model\r\n\r\nE2E machine learning involves several additional step e.g data exploration, feature selection and principal component analysis,model selection etc. Many of these steps are ignored here for brevity.\r\n\r\n\r\n\r\n", "metadata": {} }, { @@ -33,9 +33,9 @@ "metadata": {}, "outputs": [ { + "output_type": "stream", "name": "stdout", - "text": "Number of rows: 32561, Number of coulumns : 15\nroot\n |-- age: integer (nullable = true)\n |-- workclass: string (nullable = true)\n |-- fnlwgt: integer (nullable = true)\n |-- education: string (nullable = true)\n |-- education-num: integer (nullable = true)\n |-- marital-status: string (nullable = true)\n |-- occupation: string (nullable = true)\n |-- relationship: string (nullable = true)\n |-- race: string (nullable = true)\n |-- sex: string (nullable = true)\n |-- capital-gain: integer (nullable = true)\n |-- capital-loss: integer (nullable = true)\n |-- hours-per-week: integer (nullable = true)\n |-- native-country: string (nullable = true)\n |-- income: string (nullable = true)\n\nroot\n |-- age: integer (nullable = true)\n |-- workclass: string (nullable = true)\n |-- fnlwgt: integer (nullable = true)\n |-- education: string (nullable = true)\n |-- education_num: integer (nullable = true)\n |-- marital_status: string (nullable = true)\n |-- occupation: string (nullable = true)\n |-- relationship: string (nullable = true)\n |-- race: string (nullable = true)\n |-- sex: string (nullable = true)\n |-- capital_gain: integer (nullable = true)\n |-- capital_loss: integer (nullable = true)\n |-- hours_per_week: integer (nullable = true)\n |-- native_country: string (nullable = true)\n |-- income: string (nullable = true)", - "output_type": "stream" + "text": "Number of rows: 32561, Number of coulumns : 15\nroot\n |-- age: integer (nullable = true)\n |-- workclass: string (nullable = true)\n |-- fnlwgt: integer (nullable = true)\n |-- education: string (nullable = true)\n |-- education-num: integer (nullable = true)\n |-- marital-status: string (nullable = true)\n |-- occupation: string (nullable = true)\n |-- relationship: string (nullable = true)\n |-- race: string (nullable = true)\n |-- sex: string (nullable = true)\n |-- capital-gain: integer (nullable = true)\n |-- capital-loss: integer (nullable = true)\n |-- hours-per-week: integer (nullable = true)\n |-- native-country: string (nullable = true)\n |-- income: string (nullable = true)\n\nroot\n |-- age: integer (nullable = true)\n |-- workclass: string (nullable = true)\n |-- fnlwgt: integer (nullable = true)\n |-- education: string (nullable = true)\n |-- education_num: integer (nullable = true)\n |-- marital_status: string (nullable = true)\n |-- occupation: string (nullable = true)\n |-- relationship: string (nullable = true)\n |-- race: string (nullable = true)\n |-- sex: string (nullable = true)\n |-- capital_gain: integer (nullable = true)\n |-- capital_loss: integer (nullable = true)\n |-- hours_per_week: integer (nullable = true)\n |-- native_country: string (nullable = true)\n |-- income: string (nullable = true)" } ], "execution_count": 3 @@ -46,9 +46,9 @@ "metadata": {}, "outputs": [ { + "output_type": "stream", "name": "stdout", - "text": "Select few columns to see the data\n+------+---+--------------+\n|income|age|hours_per_week|\n+------+---+--------------+\n| <=50K| 39| 40|\n| <=50K| 50| 13|\n| <=50K| 38| 40|\n| <=50K| 53| 40|\n| <=50K| 28| 40|\n| <=50K| 37| 40|\n| <=50K| 49| 16|\n| >50K| 52| 45|\n| >50K| 31| 50|\n| >50K| 42| 40|\n+------+---+--------------+\nonly showing top 10 rows\n\nNumber of distinct values for income\n+------+\n|income|\n+------+\n| <=50K|\n| >50K|\n+------+\n\nAdded numeric column(income_code) derived from income column\n+------+---+--------------+-----------+\n|income|age|hours_per_week|income_code|\n+------+---+--------------+-----------+\n| <=50K| 39| 40| 0|\n| <=50K| 50| 13| 0|\n| <=50K| 38| 40| 0|\n| <=50K| 53| 40| 0|\n| <=50K| 28| 40| 0|\n| <=50K| 37| 40| 0|\n| <=50K| 49| 16| 0|\n| >50K| 52| 45| 1|\n| >50K| 31| 50| 1|\n| >50K| 42| 40| 1|\n+------+---+--------------+-----------+\nonly showing top 10 rows\n\nPrint a statistical summary of a few columns\n+-------+------+------------------+------------------+-------------------+\n|summary|income| age| hours_per_week| income_code|\n+-------+------+------------------+------------------+-------------------+\n| count| 32561| 32561| 32561| 32561|\n| mean| null| 38.58164675532078|40.437455852092995| 0.2408095574460244|\n| stddev| null|13.640432553581356|12.347428681731838|0.42758148856469247|\n| min| <=50K| 17| 1| 0|\n| max| >50K| 90| 99| 1|\n+-------+------+------------------+------------------+-------------------+\n\nCalculate Co variance between a few columns to understand features to use\nCovariance between income and hours_per_week is 1.2\nCovariance between income and age is 1.4", - "output_type": "stream" + "text": "Select few columns to see the data\n+------+---+--------------+\n|income|age|hours_per_week|\n+------+---+--------------+\n| <=50K| 39| 40|\n| <=50K| 50| 13|\n| <=50K| 38| 40|\n| <=50K| 53| 40|\n| <=50K| 28| 40|\n| <=50K| 37| 40|\n| <=50K| 49| 16|\n| >50K| 52| 45|\n| >50K| 31| 50|\n| >50K| 42| 40|\n+------+---+--------------+\nonly showing top 10 rows\n\nNumber of distinct values for income\n+------+\n|income|\n+------+\n| <=50K|\n| >50K|\n+------+\n\nAdded numeric column(income_code) derived from income column\n+------+---+--------------+-----------+\n|income|age|hours_per_week|income_code|\n+------+---+--------------+-----------+\n| <=50K| 39| 40| 0|\n| <=50K| 50| 13| 0|\n| <=50K| 38| 40| 0|\n| <=50K| 53| 40| 0|\n| <=50K| 28| 40| 0|\n| <=50K| 37| 40| 0|\n| <=50K| 49| 16| 0|\n| >50K| 52| 45| 1|\n| >50K| 31| 50| 1|\n| >50K| 42| 40| 1|\n+------+---+--------------+-----------+\nonly showing top 10 rows\n\nPrint a statistical summary of a few columns\n+-------+------+------------------+------------------+-------------------+\n|summary|income| age| hours_per_week| income_code|\n+-------+------+------------------+------------------+-------------------+\n| count| 32561| 32561| 32561| 32561|\n| mean| null| 38.58164675532078|40.437455852092995| 0.2408095574460244|\n| stddev| null|13.640432553581356|12.347428681731838|0.42758148856469247|\n| min| <=50K| 17| 1| 0|\n| max| >50K| 90| 99| 1|\n+-------+------+------------------+------------------+-------------------+\n\nCalculate Co variance between a few columns to understand features to use\nCovariance between income and hours_per_week is 1.2\nCovariance between income and age is 1.4" } ], "execution_count": 4 @@ -59,9 +59,9 @@ "metadata": {}, "outputs": [ { + "output_type": "stream", "name": "stdout", - "text": "label = income\nfeatures = ['age', 'hours_per_week']\nCount of rows that are <=50K 24720\nCount of rows that are >50K 7841", - "output_type": "stream" + "text": "label = income\nfeatures = ['age', 'hours_per_week']\nCount of rows that are <=50K 24720\nCount of rows that are >50K 7841" } ], "execution_count": 5 @@ -77,9 +77,9 @@ "metadata": {}, "outputs": [ { + "output_type": "stream", "name": "stdout", - "text": "train (24469, 3)\ntest (8092, 3)\ntrain and test datasets saved to /spark_ml/AdultCensusIncomeTrain and /spark_ml/AdultCensusIncomeTest", - "output_type": "stream" + "text": "train (24469, 3)\ntest (8092, 3)\ntrain and test datasets saved to /spark_ml/AdultCensusIncomeTrain and /spark_ml/AdultCensusIncomeTest" } ], "execution_count": 6 @@ -95,9 +95,9 @@ "metadata": {}, "outputs": [ { + "output_type": "stream", "name": "stdout", - "text": "Using LogisticRegression model with Regularization Rate of 0.1.\nPipeline Created\nModel Trained\nModel is PipelineModel_e5284bc61285\nModel Stages [StringIndexer_1ecf86c8d2ae, VectorAssembler_450ee37e6955, LogisticRegressionModel: uid = LogisticRegression_deb52c17940d, numClasses = 2, numFeatures = 2]", - "output_type": "stream" + "text": "Using LogisticRegression model with Regularization Rate of 0.1.\nPipeline Created\nModel Trained\nModel is PipelineModel_e5284bc61285\nModel Stages [StringIndexer_1ecf86c8d2ae, VectorAssembler_450ee37e6955, LogisticRegressionModel: uid = LogisticRegression_deb52c17940d, numClasses = 2, numFeatures = 2]" } ], "execution_count": 7 @@ -113,9 +113,9 @@ "metadata": {}, "outputs": [ { + "output_type": "stream", "name": "stdout", - "text": "Area under ROC: 0.7363559303440261\nArea Under PR: 0.39475773290351296\n+------+-----+----------+\n|income|label|prediction|\n+------+-----+----------+\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| >50K| 1.0| 1.0|\n| >50K| 1.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| >50K| 1.0| 1.0|\n| >50K| 1.0| 1.0|\n| <=50K| 0.0| 1.0|\n| >50K| 1.0| 1.0|\n| <=50K| 0.0| 1.0|\n| >50K| 1.0| 1.0|\n| <=50K| 0.0| 1.0|\n+------+-----+----------+\nonly showing top 20 rows", - "output_type": "stream" + "text": "Area under ROC: 0.7363559303440261\nArea Under PR: 0.39475773290351296\n+------+-----+----------+\n|income|label|prediction|\n+------+-----+----------+\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| >50K| 1.0| 1.0|\n| >50K| 1.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| <=50K| 0.0| 1.0|\n| >50K| 1.0| 1.0|\n| >50K| 1.0| 1.0|\n| <=50K| 0.0| 1.0|\n| >50K| 1.0| 1.0|\n| <=50K| 0.0| 1.0|\n| >50K| 1.0| 1.0|\n| <=50K| 0.0| 1.0|\n+------+-----+----------+\nonly showing top 20 rows" } ], "execution_count": 8 @@ -131,9 +131,9 @@ "metadata": {}, "outputs": [ { + "output_type": "stream", "name": "stdout", - "text": "saved model to /spark_ml/AdultCensus.mml\nSuccessfully loaded from /spark_ml/AdultCensus.mml", - "output_type": "stream" + "text": "saved model to /spark_ml/AdultCensus.mml\nSuccessfully loaded from /spark_ml/AdultCensus.mml" } ], "execution_count": 9 @@ -149,9 +149,9 @@ "metadata": {}, "outputs": [ { + "output_type": "stream", "name": "stdout", - "text": "persist the mleap bundle from local to hdfs", - "output_type": "stream" + "text": "persist the mleap bundle from local to hdfs" } ], "execution_count": 10