diff --git a/02_end_to_end_machine_learning_project.ipynb b/02_end_to_end_machine_learning_project.ipynb index 02c3bf9..9971e97 100644 --- a/02_end_to_end_machine_learning_project.ipynb +++ b/02_end_to_end_machine_learning_project.ipynb @@ -59,7 +59,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "It also requires Scikit-Learn ≥ 1.0:" + "It also requires Scikit-Learn ≥ 1.0.1:" ] }, { @@ -200,7 +200,6 @@ "source": [ "# Not in the book\n", "\n", - "# Where to save the figures\n", "IMAGES_PATH = Path() / \"images\" / \"end_to_end_project\"\n", "IMAGES_PATH.mkdir(parents=True, exist_ok=True)\n", "\n", @@ -220,7 +219,7 @@ "import matplotlib.pyplot as plt\n", "\n", "housing.hist(bins=50, figsize=(12, 8))\n", - "save_fig(\"attribute_histogram_plots\") # save_fig() lines are never in the book\n", + "save_fig(\"attribute_histogram_plots\") # not in the book\n", "plt.show()" ] }, @@ -418,7 +417,7 @@ "housing[\"income_cat\"].value_counts().sort_index().plot.bar(rot=0, grid=True)\n", "plt.xlabel(\"Income category\")\n", "plt.ylabel(\"Number of districts\")\n", - "save_fig(\"housing_income_cat_bar_plot\")\n", + "save_fig(\"housing_income_cat_bar_plot\") # not in the book\n", "plt.show()" ] }, @@ -556,7 +555,7 @@ "outputs": [], "source": [ "housing.plot(kind=\"scatter\", x=\"longitude\", y=\"latitude\", grid=True)\n", - "save_fig(\"bad_visualization_plot\")\n", + "save_fig(\"bad_visualization_plot\") # not in the book\n", "plt.show()" ] }, @@ -567,7 +566,7 @@ "outputs": [], "source": [ "housing.plot(kind=\"scatter\", x=\"longitude\", y=\"latitude\", grid=True, alpha=0.2)\n", - "save_fig(\"better_visualization_plot\")\n", + "save_fig(\"better_visualization_plot\") # not in the book\n", "plt.show()" ] }, @@ -579,9 +578,9 @@ "source": [ "housing.plot(kind=\"scatter\", x=\"longitude\", y=\"latitude\", grid=True,\n", " s=housing[\"population\"] / 100, label=\"population\",\n", - " c=\"median_house_value\", cmap=plt.get_cmap(\"jet\"), colorbar=True,\n", + " c=\"median_house_value\", cmap=\"jet\", colorbar=True,\n", " legend=True, sharex=False, figsize=(10, 7))\n", - "save_fig(\"housing_prices_scatterplot\")\n", + "save_fig(\"housing_prices_scatterplot\") # not in the book\n", "plt.show()" ] }, @@ -622,6 +621,8 @@ "metadata": {}, "outputs": [], "source": [ + "# not in the book\n", + "\n", "housing_renamed = housing.rename(columns={\n", " \"latitude\": \"Latitude\", \"longitude\": \"Longitude\",\n", " \"population\": \"Population\",\n", @@ -629,7 +630,7 @@ "housing_renamed.plot(\n", " kind=\"scatter\", x=\"Longitude\", y=\"Latitude\",\n", " s=housing_renamed[\"Population\"] / 100, label=\"Population\",\n", - " c=\"Median house value (ᴜsᴅ)\", cmap=plt.get_cmap(\"jet\"), colorbar=True,\n", + " c=\"Median house value (ᴜsᴅ)\", cmap=\"jet\", colorbar=True,\n", " legend=True, sharex=False, figsize=(10, 7))\n", "\n", "california_img = plt.imread(IMAGES_PATH / filename)\n", @@ -677,7 +678,7 @@ "attributes = [\"median_house_value\", \"median_income\", \"total_rooms\",\n", " \"housing_median_age\"]\n", "scatter_matrix(housing[attributes], figsize=(12, 8))\n", - "save_fig(\"scatter_matrix_plot\")\n", + "save_fig(\"scatter_matrix_plot\") # not in the book\n", "plt.show()" ] }, @@ -689,7 +690,7 @@ "source": [ "housing.plot(kind=\"scatter\", x=\"median_income\", y=\"median_house_value\",\n", " alpha=0.1, grid=True)\n", - "save_fig(\"income_vs_house_value_scatterplot\")\n", + "save_fig(\"income_vs_house_value_scatterplot\") # not in the book\n", "plt.show()" ] }, @@ -1183,10 +1184,18 @@ "metadata": {}, "outputs": [], "source": [ - "output_df = pd.DataFrame(cat_encoder.transform(df_test_unknown),\n", + "df_output = pd.DataFrame(cat_encoder.transform(df_test_unknown),\n", " columns=cat_encoder.get_feature_names_out(),\n", - " index=df_test_unknown.index)\n", - "output_df" + " index=df_test_unknown.index)" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": {}, + "outputs": [], + "source": [ + "df_output" ] }, { @@ -1198,7 +1207,7 @@ }, { "cell_type": "code", - "execution_count": 82, + "execution_count": 83, "metadata": {}, "outputs": [], "source": [ @@ -1210,7 +1219,7 @@ }, { "cell_type": "code", - "execution_count": 83, + "execution_count": 84, "metadata": {}, "outputs": [], "source": [ @@ -1222,7 +1231,7 @@ }, { "cell_type": "code", - "execution_count": 84, + "execution_count": 85, "metadata": {}, "outputs": [], "source": [ @@ -1246,7 +1255,7 @@ }, { "cell_type": "code", - "execution_count": 85, + "execution_count": 86, "metadata": {}, "outputs": [], "source": [ @@ -1267,7 +1276,7 @@ }, { "cell_type": "code", - "execution_count": 86, + "execution_count": 87, "metadata": {}, "outputs": [], "source": [ @@ -1278,11 +1287,12 @@ }, { "cell_type": "code", - "execution_count": 87, + "execution_count": 88, "metadata": {}, "outputs": [], "source": [ "# Not in the book\n", + "\n", "ages = np.linspace(housing[\"housing_median_age\"].min(),\n", " housing[\"housing_median_age\"].max(),\n", " 500).reshape(-1, 1)\n", @@ -1311,7 +1321,7 @@ }, { "cell_type": "code", - "execution_count": 88, + "execution_count": 89, "metadata": {}, "outputs": [], "source": [ @@ -1325,13 +1335,21 @@ "some_new_data = housing[[\"median_income\"]].iloc[:5] # pretend this is new data\n", "\n", "scaled_predictions = model.predict(some_new_data)\n", - "predictions = target_scaler.inverse_transform(scaled_predictions)\n", + "predictions = target_scaler.inverse_transform(scaled_predictions)" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": {}, + "outputs": [], + "source": [ "predictions" ] }, { "cell_type": "code", - "execution_count": 89, + "execution_count": 91, "metadata": {}, "outputs": [], "source": [ @@ -1345,7 +1363,7 @@ }, { "cell_type": "code", - "execution_count": 90, + "execution_count": 92, "metadata": {}, "outputs": [], "source": [ @@ -1368,7 +1386,7 @@ }, { "cell_type": "code", - "execution_count": 91, + "execution_count": 93, "metadata": {}, "outputs": [], "source": [ @@ -1380,32 +1398,48 @@ }, { "cell_type": "code", - "execution_count": 92, + "execution_count": 94, "metadata": {}, "outputs": [], "source": [ "rbf_transformer = FunctionTransformer(rbf_kernel,\n", " kw_args=dict(Y=[[35.]], gamma=0.1))\n", - "age_simil_35 = rbf_transformer.transform(housing[[\"housing_median_age\"]])\n", + "age_simil_35 = rbf_transformer.transform(housing[[\"housing_median_age\"]])" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "metadata": {}, + "outputs": [], + "source": [ "age_simil_35" ] }, { "cell_type": "code", - "execution_count": 93, + "execution_count": 96, "metadata": {}, "outputs": [], "source": [ "sf_coords = 37.7749, -122.41\n", "sf_transformer = FunctionTransformer(rbf_kernel,\n", - " kw_args=dict(Y=[sf_coords], gamma=0.1))\n", - "sf_simil = sf_transformer.transform(housing[[\"latitude\", \"longitude\"]])\n", + " kw_args=dict(Y=[sf_coords], gamma=0.1))\n", + "sf_simil = sf_transformer.transform(housing[[\"latitude\", \"longitude\"]])" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": {}, + "outputs": [], + "source": [ "sf_simil" ] }, { "cell_type": "code", - "execution_count": 94, + "execution_count": 98, "metadata": {}, "outputs": [], "source": [ @@ -1415,7 +1449,7 @@ }, { "cell_type": "code", - "execution_count": 95, + "execution_count": 99, "metadata": {}, "outputs": [], "source": [ @@ -1441,7 +1475,7 @@ " X = X - self.mean_\n", " return X / self.scale_\n", " \n", - " # Not in the book (left as an exercise):\n", + " # not in the book (left as an exercise):\n", " def inverse_transform(self, X):\n", " check_is_fitted(self)\n", " X = check_array(X)\n", @@ -1449,7 +1483,7 @@ " X = X * self.scale_\n", " return X + self.mean_ if self.with_mean else X\n", " \n", - " # Not in the book (left as an exercise):\n", + " # not in the book (left as an exercise):\n", " def get_feature_names_out(self, names=None):\n", " return names or getattr(self, \"feature_names_in_\",\n", " [f\"x{i}\" for i in range(self.n_features_in_)]) " @@ -1464,7 +1498,7 @@ }, { "cell_type": "code", - "execution_count": 96, + "execution_count": 100, "metadata": {}, "outputs": [], "source": [ @@ -1488,7 +1522,7 @@ }, { "cell_type": "code", - "execution_count": 97, + "execution_count": 101, "metadata": {}, "outputs": [], "source": [ @@ -1514,7 +1548,7 @@ }, { "cell_type": "code", - "execution_count": 98, + "execution_count": 102, "metadata": {}, "outputs": [], "source": [ @@ -1525,7 +1559,7 @@ }, { "cell_type": "code", - "execution_count": 99, + "execution_count": 103, "metadata": {}, "outputs": [], "source": [ @@ -1534,11 +1568,12 @@ }, { "cell_type": "code", - "execution_count": 100, + "execution_count": 104, "metadata": {}, "outputs": [], "source": [ "# Not in the book\n", + "\n", "housing_renamed = housing.rename(columns={\n", " \"latitude\": \"Latitude\", \"longitude\": \"Longitude\",\n", " \"population\": \"Population\",\n", @@ -1548,7 +1583,7 @@ "housing_renamed.plot(kind=\"scatter\", x=\"Longitude\", y=\"Latitude\", grid=True,\n", " s=housing_renamed[\"Population\"] / 100, label=\"Population\",\n", " c=\"Max cluster similarity\",\n", - " cmap=plt.get_cmap(\"jet\"), colorbar=True,\n", + " cmap=\"jet\", colorbar=True,\n", " legend=True, sharex=False, figsize=(10, 7))\n", "plt.plot(cluster_simil.kmeans_.cluster_centers_[:, 1],\n", " cluster_simil.kmeans_.cluster_centers_[:, 0],\n", @@ -1575,7 +1610,7 @@ }, { "cell_type": "code", - "execution_count": 101, + "execution_count": 105, "metadata": {}, "outputs": [], "source": [ @@ -1589,7 +1624,7 @@ }, { "cell_type": "code", - "execution_count": 102, + "execution_count": 106, "metadata": {}, "outputs": [], "source": [ @@ -1600,7 +1635,7 @@ }, { "cell_type": "code", - "execution_count": 103, + "execution_count": 107, "metadata": {}, "outputs": [], "source": [ @@ -1613,7 +1648,7 @@ }, { "cell_type": "code", - "execution_count": 104, + "execution_count": 108, "metadata": {}, "outputs": [], "source": [ @@ -1623,7 +1658,7 @@ }, { "cell_type": "code", - "execution_count": 105, + "execution_count": 109, "metadata": {}, "outputs": [], "source": [ @@ -1670,52 +1705,16 @@ "monkey_patch_get_signature_names_out()" ] }, - { - "cell_type": "code", - "execution_count": 106, - "metadata": {}, - "outputs": [], - "source": [ - "housing_num_prepared_df = pd.DataFrame(\n", - " housing_num_prepared, columns=num_pipeline.get_feature_names_out(),\n", - " index=housing_num.index)\n", - "housing_num_prepared_df.head(2) # Not in the book" - ] - }, - { - "cell_type": "code", - "execution_count": 107, - "metadata": {}, - "outputs": [], - "source": [ - "num_pipeline.steps" - ] - }, - { - "cell_type": "code", - "execution_count": 108, - "metadata": {}, - "outputs": [], - "source": [ - "num_pipeline[1]" - ] - }, - { - "cell_type": "code", - "execution_count": 109, - "metadata": {}, - "outputs": [], - "source": [ - "num_pipeline[:-1]" - ] - }, { "cell_type": "code", "execution_count": 110, "metadata": {}, "outputs": [], "source": [ - "num_pipeline.named_steps[\"simpleimputer\"]" + "df_housing_num_prepared = pd.DataFrame(\n", + " housing_num_prepared, columns=num_pipeline.get_feature_names_out(),\n", + " index=housing_num.index)\n", + "df_housing_num_prepared.head(2) # not in the book" ] }, { @@ -1724,7 +1723,7 @@ "metadata": {}, "outputs": [], "source": [ - "num_pipeline.set_params(simpleimputer__strategy=\"median\")" + "num_pipeline.steps" ] }, { @@ -1732,6 +1731,42 @@ "execution_count": 112, "metadata": {}, "outputs": [], + "source": [ + "num_pipeline[1]" + ] + }, + { + "cell_type": "code", + "execution_count": 113, + "metadata": {}, + "outputs": [], + "source": [ + "num_pipeline[:-1]" + ] + }, + { + "cell_type": "code", + "execution_count": 114, + "metadata": {}, + "outputs": [], + "source": [ + "num_pipeline.named_steps[\"simpleimputer\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "metadata": {}, + "outputs": [], + "source": [ + "num_pipeline.set_params(simpleimputer__strategy=\"median\")" + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "metadata": {}, + "outputs": [], "source": [ "from sklearn.compose import ColumnTransformer\n", "\n", @@ -1751,7 +1786,7 @@ }, { "cell_type": "code", - "execution_count": 113, + "execution_count": 117, "metadata": {}, "outputs": [], "source": [ @@ -1765,7 +1800,7 @@ }, { "cell_type": "code", - "execution_count": 114, + "execution_count": 118, "metadata": {}, "outputs": [], "source": [ @@ -1774,7 +1809,7 @@ }, { "cell_type": "code", - "execution_count": 115, + "execution_count": 119, "metadata": {}, "outputs": [], "source": [ @@ -1787,7 +1822,7 @@ }, { "cell_type": "code", - "execution_count": 116, + "execution_count": 120, "metadata": {}, "outputs": [], "source": [ @@ -1824,7 +1859,7 @@ }, { "cell_type": "code", - "execution_count": 117, + "execution_count": 121, "metadata": {}, "outputs": [], "source": [ @@ -1834,7 +1869,7 @@ }, { "cell_type": "code", - "execution_count": 118, + "execution_count": 122, "metadata": {}, "outputs": [], "source": [ @@ -1857,7 +1892,7 @@ }, { "cell_type": "code", - "execution_count": 119, + "execution_count": 123, "metadata": {}, "outputs": [], "source": [ @@ -1876,12 +1911,12 @@ }, { "cell_type": "code", - "execution_count": 120, + "execution_count": 124, "metadata": {}, "outputs": [], "source": [ "housing_predictions = lin_reg.predict(housing)\n", - "housing_predictions[:5].round(-2)" + "housing_predictions[:5].round(-2) # -2 = rounded to the nearest hundred" ] }, { @@ -1893,7 +1928,7 @@ }, { "cell_type": "code", - "execution_count": 121, + "execution_count": 125, "metadata": {}, "outputs": [], "source": [ @@ -1902,7 +1937,7 @@ }, { "cell_type": "code", - "execution_count": 122, + "execution_count": 126, "metadata": {}, "outputs": [], "source": [ @@ -1913,7 +1948,7 @@ }, { "cell_type": "code", - "execution_count": 123, + "execution_count": 127, "metadata": {}, "outputs": [], "source": [ @@ -1926,7 +1961,7 @@ }, { "cell_type": "code", - "execution_count": 124, + "execution_count": 128, "metadata": {}, "outputs": [], "source": [ @@ -1938,7 +1973,7 @@ }, { "cell_type": "code", - "execution_count": 125, + "execution_count": 129, "metadata": {}, "outputs": [], "source": [ @@ -1957,7 +1992,7 @@ }, { "cell_type": "code", - "execution_count": 126, + "execution_count": 130, "metadata": {}, "outputs": [], "source": [ @@ -1969,7 +2004,7 @@ }, { "cell_type": "code", - "execution_count": 127, + "execution_count": 131, "metadata": {}, "outputs": [], "source": [ @@ -1978,7 +2013,7 @@ }, { "cell_type": "code", - "execution_count": 128, + "execution_count": 132, "metadata": {}, "outputs": [], "source": [ @@ -1997,7 +2032,7 @@ }, { "cell_type": "code", - "execution_count": 129, + "execution_count": 133, "metadata": {}, "outputs": [], "source": [ @@ -2011,7 +2046,7 @@ }, { "cell_type": "code", - "execution_count": 130, + "execution_count": 134, "metadata": {}, "outputs": [], "source": [ @@ -2027,7 +2062,7 @@ }, { "cell_type": "code", - "execution_count": 131, + "execution_count": 135, "metadata": {}, "outputs": [], "source": [ @@ -2068,7 +2103,7 @@ }, { "cell_type": "code", - "execution_count": 132, + "execution_count": 136, "metadata": {}, "outputs": [], "source": [ @@ -2098,7 +2133,7 @@ }, { "cell_type": "code", - "execution_count": 133, + "execution_count": 137, "metadata": {}, "outputs": [], "source": [ @@ -2115,7 +2150,7 @@ }, { "cell_type": "code", - "execution_count": 134, + "execution_count": 138, "metadata": {}, "outputs": [], "source": [ @@ -2124,7 +2159,7 @@ }, { "cell_type": "code", - "execution_count": 135, + "execution_count": 139, "metadata": {}, "outputs": [], "source": [ @@ -2140,18 +2175,21 @@ }, { "cell_type": "code", - "execution_count": 136, + "execution_count": 140, "metadata": {}, "outputs": [], "source": [ "cv_res = pd.DataFrame(grid_search.cv_results_)\n", "cv_res.sort_values(by=\"mean_test_score\", ascending=False, inplace=True)\n", + "\n", + "# not in the book\n", "cv_res = cv_res[[\"param_preprocessing__geo__n_clusters\",\n", " \"param_random_forest__max_features\", \"split0_test_score\",\n", " \"split1_test_score\", \"split2_test_score\", \"mean_test_score\"]]\n", "score_cols = [\"split0\", \"split1\", \"split2\", \"mean_test_rmse\"]\n", "cv_res.columns = [\"n_clusters\", \"max_features\"] + score_cols\n", "cv_res[score_cols] = -cv_res[score_cols].round().astype(np.int64)\n", + "\n", "cv_res.head()" ] }, @@ -2171,7 +2209,7 @@ }, { "cell_type": "code", - "execution_count": 137, + "execution_count": 141, "metadata": {}, "outputs": [], "source": [ @@ -2179,9 +2217,16 @@ "from sklearn.model_selection import HalvingRandomSearchCV" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Try 30 (`n_iter` × `cv`) random combinations of hyperparameters:" + ] + }, { "cell_type": "code", - "execution_count": 138, + "execution_count": 142, "metadata": {}, "outputs": [], "source": [ @@ -2191,7 +2236,6 @@ "param_distribs = {'preprocessing__geo__n_clusters': randint(low=3, high=50),\n", " 'random_forest__max_features': randint(low=2, high=20)}\n", "\n", - "# try 30 (n_iter × cv) random combinations of hyperparameters\n", "rnd_search = RandomizedSearchCV(\n", " full_pipeline, param_distributions=param_distribs, n_iter=10, cv=3,\n", " scoring='neg_root_mean_squared_error', random_state=42)\n", @@ -2201,7 +2245,7 @@ }, { "cell_type": "code", - "execution_count": 139, + "execution_count": 143, "metadata": {}, "outputs": [], "source": [ @@ -2238,7 +2282,7 @@ }, { "cell_type": "code", - "execution_count": 140, + "execution_count": 144, "metadata": { "tags": [] }, @@ -2299,7 +2343,7 @@ }, { "cell_type": "code", - "execution_count": 141, + "execution_count": 145, "metadata": { "tags": [] }, @@ -2362,18 +2406,18 @@ }, { "cell_type": "code", - "execution_count": 142, + "execution_count": 146, "metadata": {}, "outputs": [], "source": [ - "final_model = rnd_search.best_estimator_\n", + "final_model = rnd_search.best_estimator_ # includes preprocessing\n", "feature_importances = final_model[\"random_forest\"].feature_importances_\n", "feature_importances.round(2)" ] }, { "cell_type": "code", - "execution_count": 143, + "execution_count": 147, "metadata": {}, "outputs": [], "source": [ @@ -2391,7 +2435,7 @@ }, { "cell_type": "code", - "execution_count": 144, + "execution_count": 148, "metadata": {}, "outputs": [], "source": [ @@ -2400,16 +2444,8 @@ "\n", "final_predictions = final_model.predict(X_test)\n", "\n", - "final_rmse = mean_squared_error(y_test, final_predictions, squared=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 145, - "metadata": {}, - "outputs": [], - "source": [ - "final_rmse" + "final_rmse = mean_squared_error(y_test, final_predictions, squared=False)\n", + "print(final_rmse)" ] }, { @@ -2421,7 +2457,7 @@ }, { "cell_type": "code", - "execution_count": 146, + "execution_count": 149, "metadata": {}, "outputs": [], "source": [ @@ -2443,7 +2479,7 @@ }, { "cell_type": "code", - "execution_count": 147, + "execution_count": 150, "metadata": {}, "outputs": [], "source": [ @@ -2464,7 +2500,7 @@ }, { "cell_type": "code", - "execution_count": 148, + "execution_count": 151, "metadata": {}, "outputs": [], "source": [ @@ -2490,7 +2526,7 @@ }, { "cell_type": "code", - "execution_count": 149, + "execution_count": 152, "metadata": {}, "outputs": [], "source": [ @@ -2508,21 +2544,23 @@ }, { "cell_type": "code", - "execution_count": 150, + "execution_count": 153, "metadata": {}, "outputs": [], "source": [ "import joblib\n", + "\n", + "# not in the book\n", "from sklearn.cluster import KMeans\n", "from sklearn.base import BaseEstimator, TransformerMixin\n", "from sklearn.metrics.pairwise import rbf_kernel\n", "\n", - "#class ClusterSimilarity(BaseEstimator, TransformerMixin):\n", - "# [...]\n", - "\n", "def column_ratio(X):\n", " return X[:, [0]] / X[:, [1]]\n", "\n", + "#class ClusterSimilarity(BaseEstimator, TransformerMixin):\n", + "# [...]\n", + "\n", "final_model_reloaded = joblib.load(\"my_california_housing_model.pkl\")\n", "\n", "new_data = housing.iloc[:5] # pretend these are new districts\n", @@ -2531,7 +2569,7 @@ }, { "cell_type": "code", - "execution_count": 151, + "execution_count": 154, "metadata": {}, "outputs": [], "source": [ @@ -2568,7 +2606,7 @@ }, { "cell_type": "code", - "execution_count": 152, + "execution_count": 155, "metadata": {}, "outputs": [], "source": [ @@ -2598,7 +2636,7 @@ }, { "cell_type": "code", - "execution_count": 153, + "execution_count": 156, "metadata": {}, "outputs": [], "source": [ @@ -2615,7 +2653,7 @@ }, { "cell_type": "code", - "execution_count": 154, + "execution_count": 157, "metadata": {}, "outputs": [], "source": [ @@ -2652,7 +2690,7 @@ }, { "cell_type": "code", - "execution_count": 155, + "execution_count": 158, "metadata": {}, "outputs": [], "source": [ @@ -2686,7 +2724,7 @@ }, { "cell_type": "code", - "execution_count": 156, + "execution_count": 159, "metadata": {}, "outputs": [], "source": [ @@ -2703,7 +2741,7 @@ }, { "cell_type": "code", - "execution_count": 157, + "execution_count": 160, "metadata": {}, "outputs": [], "source": [ @@ -2726,7 +2764,7 @@ }, { "cell_type": "code", - "execution_count": 158, + "execution_count": 161, "metadata": {}, "outputs": [], "source": [ @@ -2766,7 +2804,7 @@ }, { "cell_type": "code", - "execution_count": 159, + "execution_count": 162, "metadata": {}, "outputs": [], "source": [ @@ -2784,7 +2822,7 @@ }, { "cell_type": "code", - "execution_count": 160, + "execution_count": 163, "metadata": {}, "outputs": [], "source": [ @@ -2826,7 +2864,7 @@ }, { "cell_type": "code", - "execution_count": 161, + "execution_count": 164, "metadata": {}, "outputs": [], "source": [ @@ -2871,7 +2909,7 @@ }, { "cell_type": "code", - "execution_count": 162, + "execution_count": 165, "metadata": {}, "outputs": [], "source": [ @@ -2887,7 +2925,7 @@ }, { "cell_type": "code", - "execution_count": 163, + "execution_count": 166, "metadata": {}, "outputs": [], "source": [ @@ -2906,7 +2944,7 @@ }, { "cell_type": "code", - "execution_count": 164, + "execution_count": 167, "metadata": {}, "outputs": [], "source": [ @@ -2922,7 +2960,7 @@ }, { "cell_type": "code", - "execution_count": 165, + "execution_count": 168, "metadata": {}, "outputs": [], "source": [ @@ -2938,7 +2976,7 @@ }, { "cell_type": "code", - "execution_count": 166, + "execution_count": 169, "metadata": {}, "outputs": [], "source": [ @@ -2952,7 +2990,7 @@ }, { "cell_type": "code", - "execution_count": 167, + "execution_count": 170, "metadata": {}, "outputs": [], "source": [ @@ -2987,7 +3025,7 @@ }, { "cell_type": "code", - "execution_count": 168, + "execution_count": 171, "metadata": {}, "outputs": [], "source": [ @@ -3009,7 +3047,7 @@ }, { "cell_type": "code", - "execution_count": 169, + "execution_count": 172, "metadata": {}, "outputs": [], "source": [