{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "### In this notebook we will be taking the original South German Credit dataset and adding bias against foreign workers" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%%capture \n", "#Cell Magic to hide output\n", "\n", "#For Synthetic Data Generation\n", "!pip install sdv\n", "#Imports\n", "import pandas as pd\n", "from sagemaker.s3 import S3Downloader\n", "from sdv.tabular import GaussianCopula" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Download data\n", "\n", "First, __download__ the data and save it in the `data` folder.\n", "\n", "\n", "$^{[2]}$ Ulrike Grömping\n", "Beuth University of Applied Sciences Berlin\n", "Website with contact information: https://prof.beuth-hochschule.de/groemping/." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
statusdurationcredit_historypurposeamountsavingsemployment_durationinstallment_ratepersonal_status_sexother_debtors...propertyageother_installment_planshousingnumber_creditsjobpeople_liabletelephoneforeign_workercredit_risk
011842104912421...22131132121
11940279913231...13631231121
22122984124221...12331122121
311240212213331...13931221111
411240217113431...23812222111
\n", "

5 rows × 21 columns

\n", "
" ], "text/plain": [ " status duration credit_history purpose amount savings \\\n", "0 1 18 4 2 1049 1 \n", "1 1 9 4 0 2799 1 \n", "2 2 12 2 9 841 2 \n", "3 1 12 4 0 2122 1 \n", "4 1 12 4 0 2171 1 \n", "\n", " employment_duration installment_rate personal_status_sex other_debtors \\\n", "0 2 4 2 1 \n", "1 3 2 3 1 \n", "2 4 2 2 1 \n", "3 3 3 3 1 \n", "4 3 4 3 1 \n", "\n", " ... property age other_installment_plans housing number_credits job \\\n", "0 ... 2 21 3 1 1 3 \n", "1 ... 1 36 3 1 2 3 \n", "2 ... 1 23 3 1 1 2 \n", "3 ... 1 39 3 1 2 2 \n", "4 ... 2 38 1 2 2 2 \n", "\n", " people_liable telephone foreign_worker credit_risk \n", "0 2 1 2 1 \n", "1 1 1 2 1 \n", "2 2 1 2 1 \n", "3 1 1 1 1 \n", "4 2 1 1 1 \n", "\n", "[5 rows x 21 columns]" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#Load data from s3\n", "S3Downloader.download(\n", " \"s3://sagemaker-sample-files/datasets/tabular/uci_statlog_german_credit_data/SouthGermanCredit.asc\",\n", " \"data\",\n", ")\n", "#Set Column names\n", "credit_columns = [\n", " \"status\",\n", " \"duration\",\n", " \"credit_history\",\n", " \"purpose\",\n", " \"amount\",\n", " \"savings\",\n", " \"employment_duration\",\n", " \"installment_rate\",\n", " \"personal_status_sex\",\n", " \"other_debtors\",\n", " \"present_residence\",\n", " \"property\",\n", " \"age\",\n", " \"other_installment_plans\",\n", " \"housing\",\n", " \"number_credits\",\n", " \"job\",\n", " \"people_liable\",\n", " \"telephone\",\n", " \"foreign_worker\",\n", " \"credit_risk\",\n", "]\n", "#Load South German Credit data\n", "training_data = pd.read_csv(\n", " \"data/SouthGermanCredit.asc\",\n", " names=credit_columns,\n", " header=0,\n", " sep=r\" \",\n", " engine=\"python\",\n", " na_values=\"?\",\n", ").dropna()\n", "#Take a look at first 5 rows of data\n", "training_data.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Explanation of Data Features" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$`laufkont = status`\n", " \n", " 1 : no checking account \n", " 2 : ... < 0 DM \n", " 3 : 0<= ... < 200 DM \n", " 4 : ... >= 200 DM / salary for at least 1 year\n", "\n", "$`laufzeit = duration`\n", " \n", "\n", "$`moral = credit_history`\n", " \n", " 0 : delay in paying off in the past \n", " 1 : critical account/other credits elsewhere \n", " 2 : no credits taken/all credits paid back duly\n", " 3 : existing credits paid back duly till now \n", " 4 : all credits at this bank paid back duly \n", "\n", "$`verw = purpose`\n", " \n", " 0 : others \n", " 1 : car (new) \n", " 2 : car (used) \n", " 3 : furniture/equipment\n", " 4 : radio/television \n", " 5 : domestic appliances\n", " 6 : repairs \n", " 7 : education \n", " 8 : vacation \n", " 9 : retraining \n", " 10 : business \n", "\n", "$`hoehe = amount`\n", " \n", "\n", "$`sparkont = savings`\n", " \n", " 1 : unknown/no savings account\n", " 2 : ... < 100 DM \n", " 3 : 100 <= ... < 500 DM \n", " 4 : 500 <= ... < 1000 DM \n", " 5 : ... >= 1000 DM \n", "\n", "$`beszeit = employment_duration`\n", " \n", " 1 : unemployed \n", " 2 : < 1 yr \n", " 3 : 1 <= ... < 4 yrs\n", " 4 : 4 <= ... < 7 yrs\n", " 5 : >= 7 yrs \n", "\n", "$`rate = installment_rate`\n", " \n", " 1 : >= 35 \n", " 2 : 25 <= ... < 35\n", " 3 : 20 <= ... < 25\n", " 4 : < 20 \n", "\n", "$`famges = personal_status_sex`\n", " \n", " 1 : male : divorced/separated \n", " 2 : female : non-single or male : single\n", " 3 : male : married/widowed \n", " 4 : female : single \n", "\n", "$`buerge = other_debtors`\n", " \n", " 1 : none \n", " 2 : co-applicant\n", " 3 : guarantor \n", "\n", "$`wohnzeit = present_residence`\n", " \n", " 1 : < 1 yr \n", " 2 : 1 <= ... < 4 yrs\n", " 3 : 4 <= ... < 7 yrs\n", " 4 : >= 7 yrs \n", "\n", "$`verm = property`\n", " \n", " 1 : unknown / no property \n", " 2 : car or other \n", " 3 : building soc. savings agr./life insurance\n", " 4 : real estate \n", "\n", "$`alter = age`\n", " \n", "\n", "$`weitkred = other_installment_plans`\n", " \n", " 1 : bank \n", " 2 : stores\n", " 3 : none \n", "\n", "$`wohn = housing`\n", " \n", " 1 : for free\n", " 2 : rent \n", " 3 : own \n", "\n", "$`bishkred = number_credits`\n", " \n", " 1 : 1 \n", " 2 : 2-3 \n", " 3 : 4-5 \n", " 4 : >= 6\n", "\n", "$`beruf = job`\n", " \n", " 1 : unemployed/unskilled - non-resident \n", " 2 : unskilled - resident \n", " 3 : skilled employee/official \n", " 4 : manager/self-empl./highly qualif. employee\n", "\n", "$`pers = people_liable`\n", " \n", " 1 : 3 or more\n", " 2 : 0 to 2 \n", "\n", "$`telef = telephone`\n", " \n", " 1 : no \n", " 2 : yes (under customer name)\n", "\n", "$`gastarb = foreign_worker`\n", " \n", " 1 : yes\n", " 2 : no \n", "\n", "$`kredit = credit_risk`\n", " \n", " 0 : bad \n", " 1 : good\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Synthetic Data Generation \n", "\n", "Synthetic data generation is an effective tool when studying model bias. Data can be biased towards or against specific groups or sub-groups. By generating biased data we can observe how our AI models behave towards a specific group or sub-group. One such sub-group we can examine are Foreign Workers. The model under inspection labels its predictions as 0(Bad credit) or 1(good credit), we can artificially lower their credit worthiness compared to other groups’ through synthetic data generation. \n", "\n", "For the data generation we will be using Synthetic Data Vault (https://sdv.dev/SDV/) or SDV for short. SDV is a python library that allows you to generate synthetic data that is agreeable with the statistical nature of the original dataset." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/opt/conda/lib/python3.8/site-packages/copulas/univariate/truncated_gaussian.py:45: RuntimeWarning: invalid value encountered in double_scalars\n", " a = (self.min - loc) / scale\n", "/opt/conda/lib/python3.8/site-packages/copulas/univariate/truncated_gaussian.py:46: RuntimeWarning: divide by zero encountered in double_scalars\n", " b = (self.max - loc) / scale\n" ] } ], "source": [ "#Parameters for generated data\n", "\n", "#How many rows of synthetic data \n", "Rows = 100\n", "\n", "#Select all foreign workers who were accepted (foreign_worker value 1 credit risk 1) \n", "ForeignWorkerData = training_data.loc[(training_data['foreign_worker'] == 1) & (training_data['credit_risk'] == 1)]\n", "ForeignWorkerData\n", "\n", "#Fit Foreign Worker data to SDV model (ignore warning)\n", "model = GaussianCopula()\n", "model.fit(ForeignWorkerData)\n", "\n", "#Generate Synthetic foreign worker data based on rows stated \n", "SynthForeignWorkers = model.sample(Rows)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
statusdurationcredit_historypurposeamountsavingsemployment_durationinstallment_ratepersonal_status_sexother_debtors...propertyageother_installment_planshousingnumber_creditsjobpeople_liabletelephoneforeign_workercredit_risk
031332358333321...35532132210
141002114843332...23032132110
221312203224233...12221132110
312434654152422...33122132210
44942212924231...23832231210
\n", "

5 rows × 21 columns

\n", "
" ], "text/plain": [ " status duration credit_history purpose amount savings \\\n", "0 3 13 3 2 3583 3 \n", "1 4 10 0 2 1148 4 \n", "2 2 13 1 2 2032 2 \n", "3 1 24 3 4 6541 5 \n", "4 4 9 4 2 2129 2 \n", "\n", " employment_duration installment_rate personal_status_sex other_debtors \\\n", "0 3 3 2 1 \n", "1 3 3 3 2 \n", "2 4 2 3 3 \n", "3 2 4 2 2 \n", "4 4 2 3 1 \n", "\n", " ... property age other_installment_plans housing number_credits job \\\n", "0 ... 3 55 3 2 1 3 \n", "1 ... 2 30 3 2 1 3 \n", "2 ... 1 22 2 1 1 3 \n", "3 ... 3 31 2 2 1 3 \n", "4 ... 2 38 3 2 2 3 \n", "\n", " people_liable telephone foreign_worker credit_risk \n", "0 2 2 1 0 \n", "1 2 1 1 0 \n", "2 2 1 1 0 \n", "3 2 2 1 0 \n", "4 1 2 1 0 \n", "\n", "[5 rows x 21 columns]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#We generated 100 new synthetic records of Foreign Workers based on Foreign Workers who were accepted in the original dataset. We will now take those records and convert the \"credit_risk\" label to \n", "#0 (bad credit). This will mark these Foreign Workers unfairly as bad credit, hence inserting bias into our dataset\n", "SynthForeignWorkers.loc[SynthForeignWorkers['credit_risk'] == 1, 'credit_risk'] = 0 \n", "SynthForeignWorkers.head()" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Int64Index: 1100 entries, 0 to 99\n", "Data columns (total 21 columns):\n", " # Column Non-Null Count Dtype\n", "--- ------ -------------- -----\n", " 0 status 1100 non-null int64\n", " 1 duration 1100 non-null int64\n", " 2 credit_history 1100 non-null int64\n", " 3 purpose 1100 non-null int64\n", " 4 amount 1100 non-null int64\n", " 5 savings 1100 non-null int64\n", " 6 employment_duration 1100 non-null int64\n", " 7 installment_rate 1100 non-null int64\n", " 8 personal_status_sex 1100 non-null int64\n", " 9 other_debtors 1100 non-null int64\n", " 10 present_residence 1100 non-null int64\n", " 11 property 1100 non-null int64\n", " 12 age 1100 non-null int64\n", " 13 other_installment_plans 1100 non-null int64\n", " 14 housing 1100 non-null int64\n", " 15 number_credits 1100 non-null int64\n", " 16 job 1100 non-null int64\n", " 17 people_liable 1100 non-null int64\n", " 18 telephone 1100 non-null int64\n", " 19 foreign_worker 1100 non-null int64\n", " 20 credit_risk 1100 non-null int64\n", "dtypes: int64(21)\n", "memory usage: 189.1 KB\n" ] } ], "source": [ "#Create new dataset with Synthetic Foreign workers (100) + Original South German Credit Risk (1000)\n", "frames = [training_data, SynthForeignWorkers]\n", "BiasedData1 = pd.concat(frames)\n", "BiasedData1.info()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Stored 'BiasedData1' (DataFrame)\n" ] } ], "source": [ "#Store dataframe for use in Notebook 2 and 3\n", "%store BiasedData1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Data inspection" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1100" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#Length of Biased Data\n", "len(BiasedData1)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
statusdurationcredit_historypurposeamountsavingsemployment_durationinstallment_ratepersonal_status_sexother_debtors...propertyageother_installment_planshousingnumber_creditsjobpeople_liabletelephoneforeign_workercredit_risk
011842104912421...22131132121
11940279913231...13631231121
22122984124221...12331122121
311240212213331...13931221111
411240217113431...23812222111
\n", "

5 rows × 21 columns

\n", "
" ], "text/plain": [ " status duration credit_history purpose amount savings \\\n", "0 1 18 4 2 1049 1 \n", "1 1 9 4 0 2799 1 \n", "2 2 12 2 9 841 2 \n", "3 1 12 4 0 2122 1 \n", "4 1 12 4 0 2171 1 \n", "\n", " employment_duration installment_rate personal_status_sex other_debtors \\\n", "0 2 4 2 1 \n", "1 3 2 3 1 \n", "2 4 2 2 1 \n", "3 3 3 3 1 \n", "4 3 4 3 1 \n", "\n", " ... property age other_installment_plans housing number_credits job \\\n", "0 ... 2 21 3 1 1 3 \n", "1 ... 1 36 3 1 2 3 \n", "2 ... 1 23 3 1 1 2 \n", "3 ... 1 39 3 1 2 2 \n", "4 ... 2 38 1 2 2 2 \n", "\n", " people_liable telephone foreign_worker credit_risk \n", "0 2 1 2 1 \n", "1 1 1 2 1 \n", "2 2 1 2 1 \n", "3 1 1 1 1 \n", "4 2 1 1 1 \n", "\n", "[5 rows x 21 columns]" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#View first 5 lines of biased dataset\n", "BiasedData1.head()" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "#Pie Charts for good credit/bad credit labels for Foreign Workers vs. Non-Foreign Workers \n", "\n", "#Imports \n", "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "\n", "#Select all Non-Foreign workers in the dataset\n", "BiasedDataNonForeign = BiasedData1[BiasedData1['foreign_worker']==2]\n", "#Select all Foreign workers in the dataset\n", "BiasedDataForeign = BiasedData1[BiasedData1['foreign_worker']==1]\n", "#Pie Chart for Non-Foreign workers good credit/bad credit\n", "BiasedDataNonForeign.groupby(['credit_risk']).sum().plot(kind='pie', y='foreign_worker', autopct='%1.1f%%', colors = ['red','green'], legend = None)\n", "plt.title('Credit Risk Ratio for Non-Foreign Workers')\n", "plt.show()\n", "#Pie Chart for Foreign workers good credit/bad credit\n", "BiasedDataForeign.groupby(['credit_risk']).sum().plot(kind='pie', y='foreign_worker', autopct='%1.1f%%', colors = ['red','green'])\n", "plt.title('Credit Risk Ratio for Foreign Workers')\n", "plt.legend(labels=[\"Bad Credit\",\"Good Credit\"])\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of Foreign Workers: 137\n", "Number of Non-Foreign Workers: 963\n" ] } ], "source": [ "#Check how many Foreign workers there are vs. Non-Foreign Workers\n", "print(\"Number of Foreign Workers: \",BiasedData1['foreign_worker'].value_counts()[1])\n", "print(\"Number of Non-Foreign Workers: \",BiasedData1['foreign_worker'].value_counts()[2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Data Processing" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "#Imports\n", "from sagemaker.s3 import S3Uploader\n", "from sagemaker import Session\n", "from sagemaker.sklearn.processing import SKLearnProcessor\n", "from sagemaker import get_execution_role\n", "from sagemaker.processing import ProcessingInput, ProcessingOutput\n", "\n", "session = Session()\n", "bucket = session.default_bucket()\n", "prefix = \"sagemaker/sagemaker-amt-credit-risk-model\"\n", "region = session.boto_region_name\n", "role = get_execution_role()\n", "\n", "training_data = BiasedData1 " ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "# prepare raw test data\n", "test_data = training_data.sample(frac=0.1)\n", "test_data = test_data.drop([\"credit_risk\"], axis=1)\n", "test_filename = \"test.csv\"\n", "test_columns = [\n", " \"status\",\n", " \"duration\",\n", " \"credit_history\",\n", " \"purpose\",\n", " \"amount\",\n", " \"savings\",\n", " \"employment_duration\",\n", " \"installment_rate\",\n", " \"personal_status_sex\",\n", " \"other_debtors\",\n", " \"present_residence\",\n", " \"property\",\n", " \"age\",\n", " \"other_installment_plans\",\n", " \"housing\",\n", " \"number_credits\",\n", " \"job\",\n", " \"people_liable\",\n", " \"telephone\",\n", " \"foreign_worker\",\n", "]\n", "test_data.to_csv(test_filename, index=False, header=True, columns=test_columns, sep=\",\")\n", "\n", "# prepare raw training data\n", "credit_columns = [\n", " \"status\",\n", " \"duration\",\n", " \"credit_history\",\n", " \"purpose\",\n", " \"amount\",\n", " \"savings\",\n", " \"employment_duration\",\n", " \"installment_rate\",\n", " \"personal_status_sex\",\n", " \"other_debtors\",\n", " \"present_residence\",\n", " \"property\",\n", " \"age\",\n", " \"other_installment_plans\",\n", " \"housing\",\n", " \"number_credits\",\n", " \"job\",\n", " \"people_liable\",\n", " \"telephone\",\n", " \"foreign_worker\",\n", " \"credit_risk\",\n", "]\n", "train_filename = \"train.csv\"\n", "training_data.to_csv(train_filename, index=False, header=True, columns=credit_columns, sep=\",\")" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "s3://sagemaker-us-east-2-921553072635/sagemaker/sagemaker-amt-credit-risk-model/data/test/test.csv\n", "Stored 'test_raw' (str)\n" ] } ], "source": [ "#Store raw test data in S#\n", "test_raw = S3Uploader.upload(test_filename, \"s3://{}/{}/data/test\".format(bucket, prefix))\n", "print(test_raw)\n", "%store test_raw" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "s3://sagemaker-us-east-2-921553072635/sagemaker/sagemaker-amt-credit-risk-model/data/train/train.csv\n" ] } ], "source": [ "#Store raw train data in S#\n", "train_raw = S3Uploader.upload(train_filename, \"s3://{}/{}/data/train\".format(bucket, prefix))\n", "print(train_raw)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "#Setup Processor \n", "sklearn_processor = SKLearnProcessor(\n", " role=role,\n", " base_job_name=\"sagemaker-amt-credit-risk-processing-job\",\n", " instance_type=\"ml.m5.large\",\n", " instance_count=1,\n", " framework_version=\"0.20.0\",\n", ")" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Job Name: sagemaker-amt-credit-risk-processing-jo-2023-01-26-23-26-48-832\n", "Inputs: [{'InputName': 'raw_data', 'AppManaged': False, 'S3Input': {'S3Uri': 's3://sagemaker-us-east-2-921553072635/sagemaker/sagemaker-amt-credit-risk-model/data/train/', 'LocalPath': '/opt/ml/processing/input', 'S3DataType': 'S3Prefix', 'S3InputMode': 'File', 'S3DataDistributionType': 'FullyReplicated', 'S3CompressionType': 'None'}}, {'InputName': 'code', 'AppManaged': False, 'S3Input': {'S3Uri': 's3://sagemaker-us-east-2-921553072635/sagemaker-amt-credit-risk-processing-jo-2023-01-26-23-26-48-832/input/code/preprocessor.py', 'LocalPath': '/opt/ml/processing/input/code', 'S3DataType': 'S3Prefix', 'S3InputMode': 'File', 'S3DataDistributionType': 'FullyReplicated', 'S3CompressionType': 'None'}}]\n", "Outputs: [{'OutputName': 'train_data', 'AppManaged': False, 'S3Output': {'S3Uri': 's3://sagemaker-us-east-2-921553072635/sagemaker/sagemaker-amt-credit-risk-model/data/preprocessed/train/', 'LocalPath': '/opt/ml/processing/train', 'S3UploadMode': 'EndOfJob'}}, {'OutputName': 'val_data', 'AppManaged': False, 'S3Output': {'S3Uri': 's3://sagemaker-us-east-2-921553072635/sagemaker/sagemaker-amt-credit-risk-model/data/preprocessed/val/', 'LocalPath': '/opt/ml/processing/val', 'S3UploadMode': 'EndOfJob'}}, {'OutputName': 'model', 'AppManaged': False, 'S3Output': {'S3Uri': 's3://sagemaker-us-east-2-921553072635/sagemaker/sagemaker-amt-credit-risk-model/sklearn/', 'LocalPath': '/opt/ml/processing/model', 'S3UploadMode': 'EndOfJob'}}]\n", "....................................................!" ] } ], "source": [ "#Run Processor\n", "raw_data_path = \"s3://{0}/{1}/data/train/\".format(bucket, prefix)\n", "train_data_path = \"s3://{0}/{1}/data/preprocessed/train/\".format(bucket, prefix)\n", "val_data_path = \"s3://{0}/{1}/data/preprocessed/val/\".format(bucket, prefix)\n", "model_path = \"s3://{0}/{1}/sklearn/\".format(bucket, prefix)\n", "\n", "\n", "sklearn_processor.run(\n", " code=\"processing/preprocessor.py\",\n", " inputs=[\n", " ProcessingInput(\n", " input_name=\"raw_data\", source=raw_data_path, destination=\"/opt/ml/processing/input\"\n", " )\n", " ],\n", " outputs=[\n", " ProcessingOutput(\n", " output_name=\"train_data\", source=\"/opt/ml/processing/train\", destination=train_data_path\n", " ),\n", " ProcessingOutput(\n", " output_name=\"val_data\", source=\"/opt/ml/processing/val\", destination=val_data_path\n", " ),\n", " ProcessingOutput(\n", " output_name=\"model\", source=\"/opt/ml/processing/model\", destination=model_path\n", " ),\n", " ],\n", " arguments=[\"--train-test-split-ratio\", \"0.2\"],\n", " logs=False,\n", ")" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Stored 'train_data_path' (str)\n", "Stored 'val_data_path' (str)\n", "Stored 'model_path' (str)\n" ] } ], "source": [ "#Store Path to be used in later notebooks \n", "%store train_data_path \n", "%store val_data_path\n", "%store model_path " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### After ensuring every cell in this notebook has run correctly, you can now make your way over to the Notebook named \"2-Single-AMT.ipynb\" on the left menu" ] } ], "metadata": { "instance_type": "ml.t3.medium", "kernelspec": { "display_name": "Python 3 (Data Science 2.0)", "language": "python", "name": "python3__SAGEMAKER_INTERNAL__arn:aws:sagemaker:us-east-2:429704687514:image/sagemaker-data-science-38" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.13" } }, "nbformat": 4, "nbformat_minor": 5 }