├── Breast_cancer_data.csv ├── K-means Clustering.ipynb ├── KNN Classification + Regression.ipynb ├── README.md ├── airfoil_noise_data.csv ├── decision tree classification.ipynb ├── decision tree regression.ipynb ├── linear regression.ipynb ├── logistic regression.ipynb ├── naive bayes.ipynb └── sgd.ipynb /Breast_cancer_data.csv: -------------------------------------------------------------------------------- 1 | mean_radius,mean_texture,mean_perimeter,mean_area,mean_smoothness,diagnosis 2 | 17.99,10.38,122.8,1001.0,0.1184,0 3 | 20.57,17.77,132.9,1326.0,0.08474,0 4 | 19.69,21.25,130.0,1203.0,0.1096,0 5 | 11.42,20.38,77.58,386.1,0.1425,0 6 | 20.29,14.34,135.1,1297.0,0.1003,0 7 | 12.45,15.7,82.57,477.1,0.1278,0 8 | 18.25,19.98,119.6,1040.0,0.09463,0 9 | 13.71,20.83,90.2,577.9,0.1189,0 10 | 13.0,21.82,87.5,519.8,0.1273,0 11 | 12.46,24.04,83.97,475.9,0.1186,0 12 | 16.02,23.24,102.7,797.8,0.08206,0 13 | 15.78,17.89,103.6,781.0,0.0971,0 14 | 19.17,24.8,132.4,1123.0,0.0974,0 15 | 15.85,23.95,103.7,782.7,0.08401,0 16 | 13.73,22.61,93.6,578.3,0.1131,0 17 | 14.54,27.54,96.73,658.8,0.1139,0 18 | 14.68,20.13,94.74,684.5,0.09867,0 19 | 16.13,20.68,108.1,798.8,0.117,0 20 | 19.81,22.15,130.0,1260.0,0.09831,0 21 | 13.54,14.36,87.46,566.3,0.09779,1 22 | 13.08,15.71,85.63,520.0,0.1075,1 23 | 9.504,12.44,60.34,273.9,0.1024,1 24 | 15.34,14.26,102.5,704.4,0.1073,0 25 | 21.16,23.04,137.2,1404.0,0.09428,0 26 | 16.65,21.38,110.0,904.6,0.1121,0 27 | 17.14,16.4,116.0,912.7,0.1186,0 28 | 14.58,21.53,97.41,644.8,0.1054,0 29 | 18.61,20.25,122.1,1094.0,0.0944,0 30 | 15.3,25.27,102.4,732.4,0.1082,0 31 | 17.57,15.05,115.0,955.1,0.09847,0 32 | 18.63,25.11,124.8,1088.0,0.1064,0 33 | 11.84,18.7,77.93,440.6,0.1109,0 34 | 17.02,23.98,112.8,899.3,0.1197,0 35 | 19.27,26.47,127.9,1162.0,0.09401,0 36 | 16.13,17.88,107.0,807.2,0.104,0 37 | 16.74,21.59,110.1,869.5,0.0961,0 38 | 14.25,21.72,93.63,633.0,0.09823,0 39 | 13.03,18.42,82.61,523.8,0.08983,1 40 | 14.99,25.2,95.54,698.8,0.09387,0 41 | 13.48,20.82,88.4,559.2,0.1016,0 42 | 13.44,21.58,86.18,563.0,0.08162,0 43 | 10.95,21.35,71.9,371.1,0.1227,0 44 | 19.07,24.81,128.3,1104.0,0.09081,0 45 | 13.28,20.28,87.32,545.2,0.1041,0 46 | 13.17,21.81,85.42,531.5,0.09714,0 47 | 18.65,17.6,123.7,1076.0,0.1099,0 48 | 8.196,16.84,51.71,201.9,0.086,1 49 | 13.17,18.66,85.98,534.6,0.1158,0 50 | 12.05,14.63,78.04,449.3,0.1031,1 51 | 13.49,22.3,86.91,561.0,0.08752,1 52 | 11.76,21.6,74.72,427.9,0.08637,1 53 | 13.64,16.34,87.21,571.8,0.07685,1 54 | 11.94,18.24,75.71,437.6,0.08261,1 55 | 18.22,18.7,120.3,1033.0,0.1148,0 56 | 15.1,22.02,97.26,712.8,0.09056,0 57 | 11.52,18.75,73.34,409.0,0.09524,1 58 | 19.21,18.57,125.5,1152.0,0.1053,0 59 | 14.71,21.59,95.55,656.9,0.1137,0 60 | 13.05,19.31,82.61,527.2,0.0806,1 61 | 8.618,11.79,54.34,224.5,0.09752,1 62 | 10.17,14.88,64.55,311.9,0.1134,1 63 | 8.598,20.98,54.66,221.8,0.1243,1 64 | 14.25,22.15,96.42,645.7,0.1049,0 65 | 9.173,13.86,59.2,260.9,0.07721,1 66 | 12.68,23.84,82.69,499.0,0.1122,0 67 | 14.78,23.94,97.4,668.3,0.1172,0 68 | 9.465,21.01,60.11,269.4,0.1044,1 69 | 11.31,19.04,71.8,394.1,0.08139,1 70 | 9.029,17.33,58.79,250.5,0.1066,1 71 | 12.78,16.49,81.37,502.5,0.09831,1 72 | 18.94,21.31,123.6,1130.0,0.09009,0 73 | 8.888,14.64,58.79,244.0,0.09783,1 74 | 17.2,24.52,114.2,929.4,0.1071,0 75 | 13.8,15.79,90.43,584.1,0.1007,0 76 | 12.31,16.52,79.19,470.9,0.09172,1 77 | 16.07,19.65,104.1,817.7,0.09168,0 78 | 13.53,10.94,87.91,559.2,0.1291,1 79 | 18.05,16.15,120.2,1006.0,0.1065,0 80 | 20.18,23.97,143.7,1245.0,0.1286,0 81 | 12.86,18.0,83.19,506.3,0.09934,1 82 | 11.45,20.97,73.81,401.5,0.1102,1 83 | 13.34,15.86,86.49,520.0,0.1078,1 84 | 25.22,24.91,171.5,1878.0,0.1063,0 85 | 19.1,26.29,129.1,1132.0,0.1215,0 86 | 12.0,15.65,76.95,443.3,0.09723,1 87 | 18.46,18.52,121.1,1075.0,0.09874,0 88 | 14.48,21.46,94.25,648.2,0.09444,0 89 | 19.02,24.59,122.0,1076.0,0.09029,0 90 | 12.36,21.8,79.78,466.1,0.08772,1 91 | 14.64,15.24,95.77,651.9,0.1132,1 92 | 14.62,24.02,94.57,662.7,0.08974,1 93 | 15.37,22.76,100.2,728.2,0.092,0 94 | 13.27,14.76,84.74,551.7,0.07355,1 95 | 13.45,18.3,86.6,555.1,0.1022,1 96 | 15.06,19.83,100.3,705.6,0.1039,0 97 | 20.26,23.03,132.4,1264.0,0.09078,0 98 | 12.18,17.84,77.79,451.1,0.1045,1 99 | 9.787,19.94,62.11,294.5,0.1024,1 100 | 11.6,12.84,74.34,412.6,0.08983,1 101 | 14.42,19.77,94.48,642.5,0.09752,0 102 | 13.61,24.98,88.05,582.7,0.09488,0 103 | 6.981,13.43,43.79,143.5,0.117,1 104 | 12.18,20.52,77.22,458.7,0.08013,1 105 | 9.876,19.4,63.95,298.3,0.1005,1 106 | 10.49,19.29,67.41,336.1,0.09989,1 107 | 13.11,15.56,87.21,530.2,0.1398,0 108 | 11.64,18.33,75.17,412.5,0.1142,1 109 | 12.36,18.54,79.01,466.7,0.08477,1 110 | 22.27,19.67,152.8,1509.0,0.1326,0 111 | 11.34,21.26,72.48,396.5,0.08759,1 112 | 9.777,16.99,62.5,290.2,0.1037,1 113 | 12.63,20.76,82.15,480.4,0.09933,1 114 | 14.26,19.65,97.83,629.9,0.07837,1 115 | 10.51,20.19,68.64,334.2,0.1122,1 116 | 8.726,15.83,55.84,230.9,0.115,1 117 | 11.93,21.53,76.53,438.6,0.09768,1 118 | 8.95,15.76,58.74,245.2,0.09462,1 119 | 14.87,16.67,98.64,682.5,0.1162,0 120 | 15.78,22.91,105.7,782.6,0.1155,0 121 | 17.95,20.01,114.2,982.0,0.08402,0 122 | 11.41,10.82,73.34,403.3,0.09373,1 123 | 18.66,17.12,121.4,1077.0,0.1054,0 124 | 24.25,20.2,166.2,1761.0,0.1447,0 125 | 14.5,10.89,94.28,640.7,0.1101,1 126 | 13.37,16.39,86.1,553.5,0.07115,1 127 | 13.85,17.21,88.44,588.7,0.08785,1 128 | 13.61,24.69,87.76,572.6,0.09258,0 129 | 19.0,18.91,123.4,1138.0,0.08217,0 130 | 15.1,16.39,99.58,674.5,0.115,1 131 | 19.79,25.12,130.4,1192.0,0.1015,0 132 | 12.19,13.29,79.08,455.8,0.1066,1 133 | 15.46,19.48,101.7,748.9,0.1092,0 134 | 16.16,21.54,106.2,809.8,0.1008,0 135 | 15.71,13.93,102.0,761.7,0.09462,1 136 | 18.45,21.91,120.2,1075.0,0.0943,0 137 | 12.77,22.47,81.72,506.3,0.09055,0 138 | 11.71,16.67,74.72,423.6,0.1051,1 139 | 11.43,15.39,73.06,399.8,0.09639,1 140 | 14.95,17.57,96.85,678.1,0.1167,0 141 | 11.28,13.39,73.0,384.8,0.1164,1 142 | 9.738,11.97,61.24,288.5,0.0925,1 143 | 16.11,18.05,105.1,813.0,0.09721,0 144 | 11.43,17.31,73.66,398.0,0.1092,1 145 | 12.9,15.92,83.74,512.2,0.08677,1 146 | 10.75,14.97,68.26,355.3,0.07793,1 147 | 11.9,14.65,78.11,432.8,0.1152,1 148 | 11.8,16.58,78.99,432.0,0.1091,0 149 | 14.95,18.77,97.84,689.5,0.08138,1 150 | 14.44,15.18,93.97,640.1,0.0997,1 151 | 13.74,17.91,88.12,585.0,0.07944,1 152 | 13.0,20.78,83.51,519.4,0.1135,1 153 | 8.219,20.7,53.27,203.9,0.09405,1 154 | 9.731,15.34,63.78,300.2,0.1072,1 155 | 11.15,13.08,70.87,381.9,0.09754,1 156 | 13.15,15.34,85.31,538.9,0.09384,1 157 | 12.25,17.94,78.27,460.3,0.08654,1 158 | 17.68,20.74,117.4,963.7,0.1115,0 159 | 16.84,19.46,108.4,880.2,0.07445,1 160 | 12.06,12.74,76.84,448.6,0.09311,1 161 | 10.9,12.96,68.69,366.8,0.07515,1 162 | 11.75,20.18,76.1,419.8,0.1089,1 163 | 19.19,15.94,126.3,1157.0,0.08694,0 164 | 19.59,18.15,130.7,1214.0,0.112,0 165 | 12.34,22.22,79.85,464.5,0.1012,1 166 | 23.27,22.04,152.1,1686.0,0.08439,0 167 | 14.97,19.76,95.5,690.2,0.08421,1 168 | 10.8,9.71,68.77,357.6,0.09594,1 169 | 16.78,18.8,109.3,886.3,0.08865,0 170 | 17.47,24.68,116.1,984.6,0.1049,0 171 | 14.97,16.95,96.22,685.9,0.09855,1 172 | 12.32,12.39,78.85,464.1,0.1028,1 173 | 13.43,19.63,85.84,565.4,0.09048,0 174 | 15.46,11.89,102.5,736.9,0.1257,0 175 | 11.08,14.71,70.21,372.7,0.1006,1 176 | 10.66,15.15,67.49,349.6,0.08792,1 177 | 8.671,14.45,54.42,227.2,0.09138,1 178 | 9.904,18.06,64.6,302.4,0.09699,1 179 | 16.46,20.11,109.3,832.9,0.09831,0 180 | 13.01,22.22,82.01,526.4,0.06251,1 181 | 12.81,13.06,81.29,508.8,0.08739,1 182 | 27.22,21.87,182.1,2250.0,0.1094,0 183 | 21.09,26.57,142.7,1311.0,0.1141,0 184 | 15.7,20.31,101.2,766.6,0.09597,0 185 | 11.41,14.92,73.53,402.0,0.09059,1 186 | 15.28,22.41,98.92,710.6,0.09057,0 187 | 10.08,15.11,63.76,317.5,0.09267,1 188 | 18.31,18.58,118.6,1041.0,0.08588,0 189 | 11.71,17.19,74.68,420.3,0.09774,1 190 | 11.81,17.39,75.27,428.9,0.1007,1 191 | 12.3,15.9,78.83,463.7,0.0808,1 192 | 14.22,23.12,94.37,609.9,0.1075,0 193 | 12.77,21.41,82.02,507.4,0.08749,1 194 | 9.72,18.22,60.73,288.1,0.0695,1 195 | 12.34,26.86,81.15,477.4,0.1034,0 196 | 14.86,23.21,100.4,671.4,0.1044,0 197 | 12.91,16.33,82.53,516.4,0.07941,1 198 | 13.77,22.29,90.63,588.9,0.12,0 199 | 18.08,21.84,117.4,1024.0,0.07371,0 200 | 19.18,22.49,127.5,1148.0,0.08523,0 201 | 14.45,20.22,94.49,642.7,0.09872,0 202 | 12.23,19.56,78.54,461.0,0.09586,1 203 | 17.54,19.32,115.1,951.6,0.08968,0 204 | 23.29,26.67,158.9,1685.0,0.1141,0 205 | 13.81,23.75,91.56,597.8,0.1323,0 206 | 12.47,18.6,81.09,481.9,0.09965,1 207 | 15.12,16.68,98.78,716.6,0.08876,0 208 | 9.876,17.27,62.92,295.4,0.1089,1 209 | 17.01,20.26,109.7,904.3,0.08772,0 210 | 13.11,22.54,87.02,529.4,0.1002,1 211 | 15.27,12.91,98.17,725.5,0.08182,1 212 | 20.58,22.14,134.7,1290.0,0.0909,0 213 | 11.84,18.94,75.51,428.0,0.08871,1 214 | 28.11,18.47,188.5,2499.0,0.1142,0 215 | 17.42,25.56,114.5,948.0,0.1006,0 216 | 14.19,23.81,92.87,610.7,0.09463,0 217 | 13.86,16.93,90.96,578.9,0.1026,0 218 | 11.89,18.35,77.32,432.2,0.09363,1 219 | 10.2,17.48,65.05,321.2,0.08054,1 220 | 19.8,21.56,129.7,1230.0,0.09383,0 221 | 19.53,32.47,128.0,1223.0,0.0842,0 222 | 13.65,13.16,87.88,568.9,0.09646,1 223 | 13.56,13.9,88.59,561.3,0.1051,1 224 | 10.18,17.53,65.12,313.1,0.1061,1 225 | 15.75,20.25,102.6,761.3,0.1025,0 226 | 13.27,17.02,84.55,546.4,0.08445,1 227 | 14.34,13.47,92.51,641.2,0.09906,1 228 | 10.44,15.46,66.62,329.6,0.1053,1 229 | 15.0,15.51,97.45,684.5,0.08371,1 230 | 12.62,23.97,81.35,496.4,0.07903,1 231 | 12.83,22.33,85.26,503.2,0.1088,0 232 | 17.05,19.08,113.4,895.0,0.1141,0 233 | 11.32,27.08,71.76,395.7,0.06883,1 234 | 11.22,33.81,70.79,386.8,0.0778,1 235 | 20.51,27.81,134.4,1319.0,0.09159,0 236 | 9.567,15.91,60.21,279.6,0.08464,1 237 | 14.03,21.25,89.79,603.4,0.0907,1 238 | 23.21,26.97,153.5,1670.0,0.09509,0 239 | 20.48,21.46,132.5,1306.0,0.08355,0 240 | 14.22,27.85,92.55,623.9,0.08223,1 241 | 17.46,39.28,113.4,920.6,0.09812,0 242 | 13.64,15.6,87.38,575.3,0.09423,1 243 | 12.42,15.04,78.61,476.5,0.07926,1 244 | 11.3,18.19,73.93,389.4,0.09592,1 245 | 13.75,23.77,88.54,590.0,0.08043,1 246 | 19.4,23.5,129.1,1155.0,0.1027,0 247 | 10.48,19.86,66.72,337.7,0.107,1 248 | 13.2,17.43,84.13,541.6,0.07215,1 249 | 12.89,14.11,84.95,512.2,0.0876,1 250 | 10.65,25.22,68.01,347.0,0.09657,1 251 | 11.52,14.93,73.87,406.3,0.1013,1 252 | 20.94,23.56,138.9,1364.0,0.1007,0 253 | 11.5,18.45,73.28,407.4,0.09345,1 254 | 19.73,19.82,130.7,1206.0,0.1062,0 255 | 17.3,17.08,113.0,928.2,0.1008,0 256 | 19.45,19.33,126.5,1169.0,0.1035,0 257 | 13.96,17.05,91.43,602.4,0.1096,0 258 | 19.55,28.77,133.6,1207.0,0.0926,0 259 | 15.32,17.27,103.2,713.3,0.1335,0 260 | 15.66,23.2,110.2,773.5,0.1109,0 261 | 15.53,33.56,103.7,744.9,0.1063,0 262 | 20.31,27.06,132.9,1288.0,0.1,0 263 | 17.35,23.06,111.0,933.1,0.08662,0 264 | 17.29,22.13,114.4,947.8,0.08999,0 265 | 15.61,19.38,100.0,758.6,0.0784,0 266 | 17.19,22.07,111.6,928.3,0.09726,0 267 | 20.73,31.12,135.7,1419.0,0.09469,0 268 | 10.6,18.95,69.28,346.4,0.09688,1 269 | 13.59,21.84,87.16,561.0,0.07956,1 270 | 12.87,16.21,82.38,512.2,0.09425,1 271 | 10.71,20.39,69.5,344.9,0.1082,1 272 | 14.29,16.82,90.3,632.6,0.06429,1 273 | 11.29,13.04,72.23,388.0,0.09834,1 274 | 21.75,20.99,147.3,1491.0,0.09401,0 275 | 9.742,15.67,61.5,289.9,0.09037,1 276 | 17.93,24.48,115.2,998.9,0.08855,0 277 | 11.89,17.36,76.2,435.6,0.1225,1 278 | 11.33,14.16,71.79,396.6,0.09379,1 279 | 18.81,19.98,120.9,1102.0,0.08923,0 280 | 13.59,17.84,86.24,572.3,0.07948,1 281 | 13.85,15.18,88.99,587.4,0.09516,1 282 | 19.16,26.6,126.2,1138.0,0.102,0 283 | 11.74,14.02,74.24,427.3,0.07813,1 284 | 19.4,18.18,127.2,1145.0,0.1037,0 285 | 16.24,18.77,108.8,805.1,0.1066,0 286 | 12.89,15.7,84.08,516.6,0.07818,1 287 | 12.58,18.4,79.83,489.0,0.08393,1 288 | 11.94,20.76,77.87,441.0,0.08605,1 289 | 12.89,13.12,81.89,515.9,0.06955,1 290 | 11.26,19.96,73.72,394.1,0.0802,1 291 | 11.37,18.89,72.17,396.0,0.08713,1 292 | 14.41,19.73,96.03,651.0,0.08757,1 293 | 14.96,19.1,97.03,687.3,0.08992,1 294 | 12.95,16.02,83.14,513.7,0.1005,1 295 | 11.85,17.46,75.54,432.7,0.08372,1 296 | 12.72,13.78,81.78,492.1,0.09667,1 297 | 13.77,13.27,88.06,582.7,0.09198,1 298 | 10.91,12.35,69.14,363.7,0.08518,1 299 | 11.76,18.14,75.0,431.1,0.09968,0 300 | 14.26,18.17,91.22,633.1,0.06576,1 301 | 10.51,23.09,66.85,334.2,0.1015,1 302 | 19.53,18.9,129.5,1217.0,0.115,0 303 | 12.46,19.89,80.43,471.3,0.08451,1 304 | 20.09,23.86,134.7,1247.0,0.108,0 305 | 10.49,18.61,66.86,334.3,0.1068,1 306 | 11.46,18.16,73.59,403.1,0.08853,1 307 | 11.6,24.49,74.23,417.2,0.07474,1 308 | 13.2,15.82,84.07,537.3,0.08511,1 309 | 9.0,14.4,56.36,246.3,0.07005,1 310 | 13.5,12.71,85.69,566.2,0.07376,1 311 | 13.05,13.84,82.71,530.6,0.08352,1 312 | 11.7,19.11,74.33,418.7,0.08814,1 313 | 14.61,15.69,92.68,664.9,0.07618,1 314 | 12.76,13.37,82.29,504.1,0.08794,1 315 | 11.54,10.72,73.73,409.1,0.08597,1 316 | 8.597,18.6,54.09,221.2,0.1074,1 317 | 12.49,16.85,79.19,481.6,0.08511,1 318 | 12.18,14.08,77.25,461.4,0.07734,1 319 | 18.22,18.87,118.7,1027.0,0.09746,0 320 | 9.042,18.9,60.07,244.5,0.09968,1 321 | 12.43,17.0,78.6,477.3,0.07557,1 322 | 10.25,16.18,66.52,324.2,0.1061,1 323 | 20.16,19.66,131.1,1274.0,0.0802,0 324 | 12.86,13.32,82.82,504.8,0.1134,1 325 | 20.34,21.51,135.9,1264.0,0.117,0 326 | 12.2,15.21,78.01,457.9,0.08673,1 327 | 12.67,17.3,81.25,489.9,0.1028,1 328 | 14.11,12.88,90.03,616.5,0.09309,1 329 | 12.03,17.93,76.09,446.0,0.07683,1 330 | 16.27,20.71,106.9,813.7,0.1169,0 331 | 16.26,21.88,107.5,826.8,0.1165,0 332 | 16.03,15.51,105.8,793.2,0.09491,0 333 | 12.98,19.35,84.52,514.0,0.09579,1 334 | 11.22,19.86,71.94,387.3,0.1054,1 335 | 11.25,14.78,71.38,390.0,0.08306,1 336 | 12.3,19.02,77.88,464.4,0.08313,1 337 | 17.06,21.0,111.8,918.6,0.1119,0 338 | 12.99,14.23,84.08,514.3,0.09462,1 339 | 18.77,21.43,122.9,1092.0,0.09116,0 340 | 10.05,17.53,64.41,310.8,0.1007,1 341 | 23.51,24.27,155.1,1747.0,0.1069,0 342 | 14.42,16.54,94.15,641.2,0.09751,1 343 | 9.606,16.84,61.64,280.5,0.08481,1 344 | 11.06,14.96,71.49,373.9,0.1033,1 345 | 19.68,21.68,129.9,1194.0,0.09797,0 346 | 11.71,15.45,75.03,420.3,0.115,1 347 | 10.26,14.71,66.2,321.6,0.09882,1 348 | 12.06,18.9,76.66,445.3,0.08386,1 349 | 14.76,14.74,94.87,668.7,0.08875,1 350 | 11.47,16.03,73.02,402.7,0.09076,1 351 | 11.95,14.96,77.23,426.7,0.1158,1 352 | 11.66,17.07,73.7,421.0,0.07561,1 353 | 15.75,19.22,107.1,758.6,0.1243,0 354 | 25.73,17.46,174.2,2010.0,0.1149,0 355 | 15.08,25.74,98.0,716.6,0.1024,0 356 | 11.14,14.07,71.24,384.6,0.07274,1 357 | 12.56,19.07,81.92,485.8,0.0876,1 358 | 13.05,18.59,85.09,512.0,0.1082,1 359 | 13.87,16.21,88.52,593.7,0.08743,1 360 | 8.878,15.49,56.74,241.0,0.08293,1 361 | 9.436,18.32,59.82,278.6,0.1009,1 362 | 12.54,18.07,79.42,491.9,0.07436,1 363 | 13.3,21.57,85.24,546.1,0.08582,1 364 | 12.76,18.84,81.87,496.6,0.09676,1 365 | 16.5,18.29,106.6,838.1,0.09686,1 366 | 13.4,16.95,85.48,552.4,0.07937,1 367 | 20.44,21.78,133.8,1293.0,0.0915,0 368 | 20.2,26.83,133.7,1234.0,0.09905,0 369 | 12.21,18.02,78.31,458.4,0.09231,1 370 | 21.71,17.25,140.9,1546.0,0.09384,0 371 | 22.01,21.9,147.2,1482.0,0.1063,0 372 | 16.35,23.29,109.0,840.4,0.09742,0 373 | 15.19,13.21,97.65,711.8,0.07963,1 374 | 21.37,15.1,141.3,1386.0,0.1001,0 375 | 20.64,17.35,134.8,1335.0,0.09446,0 376 | 13.69,16.07,87.84,579.1,0.08302,1 377 | 16.17,16.07,106.3,788.5,0.0988,1 378 | 10.57,20.22,70.15,338.3,0.09073,1 379 | 13.46,28.21,85.89,562.1,0.07517,1 380 | 13.66,15.15,88.27,580.6,0.08268,1 381 | 11.08,18.83,73.3,361.6,0.1216,0 382 | 11.27,12.96,73.16,386.3,0.1237,1 383 | 11.04,14.93,70.67,372.7,0.07987,1 384 | 12.05,22.72,78.75,447.8,0.06935,1 385 | 12.39,17.48,80.64,462.9,0.1042,1 386 | 13.28,13.72,85.79,541.8,0.08363,1 387 | 14.6,23.29,93.97,664.7,0.08682,0 388 | 12.21,14.09,78.78,462.0,0.08108,1 389 | 13.88,16.16,88.37,596.6,0.07026,1 390 | 11.27,15.5,73.38,392.0,0.08365,1 391 | 19.55,23.21,128.9,1174.0,0.101,0 392 | 10.26,12.22,65.75,321.6,0.09996,1 393 | 8.734,16.84,55.27,234.3,0.1039,1 394 | 15.49,19.97,102.4,744.7,0.116,0 395 | 21.61,22.28,144.4,1407.0,0.1167,0 396 | 12.1,17.72,78.07,446.2,0.1029,1 397 | 14.06,17.18,89.75,609.1,0.08045,1 398 | 13.51,18.89,88.1,558.1,0.1059,1 399 | 12.8,17.46,83.05,508.3,0.08044,1 400 | 11.06,14.83,70.31,378.2,0.07741,1 401 | 11.8,17.26,75.26,431.9,0.09087,1 402 | 17.91,21.02,124.4,994.0,0.123,0 403 | 11.93,10.91,76.14,442.7,0.08872,1 404 | 12.96,18.29,84.18,525.2,0.07351,1 405 | 12.94,16.17,83.18,507.6,0.09879,1 406 | 12.34,14.95,78.29,469.1,0.08682,1 407 | 10.94,18.59,70.39,370.0,0.1004,1 408 | 16.14,14.86,104.3,800.0,0.09495,1 409 | 12.85,21.37,82.63,514.5,0.07551,1 410 | 17.99,20.66,117.8,991.7,0.1036,0 411 | 12.27,17.92,78.41,466.1,0.08685,1 412 | 11.36,17.57,72.49,399.8,0.08858,1 413 | 11.04,16.83,70.92,373.2,0.1077,1 414 | 9.397,21.68,59.75,268.8,0.07969,1 415 | 14.99,22.11,97.53,693.7,0.08515,1 416 | 15.13,29.81,96.71,719.5,0.0832,0 417 | 11.89,21.17,76.39,433.8,0.09773,1 418 | 9.405,21.7,59.6,271.2,0.1044,1 419 | 15.5,21.08,102.9,803.1,0.112,0 420 | 12.7,12.17,80.88,495.0,0.08785,1 421 | 11.16,21.41,70.95,380.3,0.1018,1 422 | 11.57,19.04,74.2,409.7,0.08546,1 423 | 14.69,13.98,98.22,656.1,0.1031,1 424 | 11.61,16.02,75.46,408.2,0.1088,1 425 | 13.66,19.13,89.46,575.3,0.09057,1 426 | 9.742,19.12,61.93,289.7,0.1075,1 427 | 10.03,21.28,63.19,307.3,0.08117,1 428 | 10.48,14.98,67.49,333.6,0.09816,1 429 | 10.8,21.98,68.79,359.9,0.08801,1 430 | 11.13,16.62,70.47,381.1,0.08151,1 431 | 12.72,17.67,80.98,501.3,0.07896,1 432 | 14.9,22.53,102.1,685.0,0.09947,0 433 | 12.4,17.68,81.47,467.8,0.1054,1 434 | 20.18,19.54,133.8,1250.0,0.1133,0 435 | 18.82,21.97,123.7,1110.0,0.1018,0 436 | 14.86,16.94,94.89,673.7,0.08924,1 437 | 13.98,19.62,91.12,599.5,0.106,0 438 | 12.87,19.54,82.67,509.2,0.09136,1 439 | 14.04,15.98,89.78,611.2,0.08458,1 440 | 13.85,19.6,88.68,592.6,0.08684,1 441 | 14.02,15.66,89.59,606.5,0.07966,1 442 | 10.97,17.2,71.73,371.5,0.08915,1 443 | 17.27,25.42,112.4,928.8,0.08331,0 444 | 13.78,15.79,88.37,585.9,0.08817,1 445 | 10.57,18.32,66.82,340.9,0.08142,1 446 | 18.03,16.85,117.5,990.0,0.08947,0 447 | 11.99,24.89,77.61,441.3,0.103,1 448 | 17.75,28.03,117.3,981.6,0.09997,0 449 | 14.8,17.66,95.88,674.8,0.09179,1 450 | 14.53,19.34,94.25,659.7,0.08388,1 451 | 21.1,20.52,138.1,1384.0,0.09684,0 452 | 11.87,21.54,76.83,432.0,0.06613,1 453 | 19.59,25.0,127.7,1191.0,0.1032,0 454 | 12.0,28.23,76.77,442.5,0.08437,1 455 | 14.53,13.98,93.86,644.2,0.1099,1 456 | 12.62,17.15,80.62,492.9,0.08583,1 457 | 13.38,30.72,86.34,557.2,0.09245,1 458 | 11.63,29.29,74.87,415.1,0.09357,1 459 | 13.21,25.25,84.1,537.9,0.08791,1 460 | 13.0,25.13,82.61,520.2,0.08369,1 461 | 9.755,28.2,61.68,290.9,0.07984,1 462 | 17.08,27.15,111.2,930.9,0.09898,0 463 | 27.42,26.27,186.9,2501.0,0.1084,0 464 | 14.4,26.99,92.25,646.1,0.06995,1 465 | 11.6,18.36,73.88,412.7,0.08508,1 466 | 13.17,18.22,84.28,537.3,0.07466,1 467 | 13.24,20.13,86.87,542.9,0.08284,1 468 | 13.14,20.74,85.98,536.9,0.08675,1 469 | 9.668,18.1,61.06,286.3,0.08311,1 470 | 17.6,23.33,119.0,980.5,0.09289,0 471 | 11.62,18.18,76.38,408.8,0.1175,1 472 | 9.667,18.49,61.49,289.1,0.08946,1 473 | 12.04,28.14,76.85,449.9,0.08752,1 474 | 14.92,14.93,96.45,686.9,0.08098,1 475 | 12.27,29.97,77.42,465.4,0.07699,1 476 | 10.88,15.62,70.41,358.9,0.1007,1 477 | 12.83,15.73,82.89,506.9,0.0904,1 478 | 14.2,20.53,92.41,618.4,0.08931,1 479 | 13.9,16.62,88.97,599.4,0.06828,1 480 | 11.49,14.59,73.99,404.9,0.1046,1 481 | 16.25,19.51,109.8,815.8,0.1026,0 482 | 12.16,18.03,78.29,455.3,0.09087,1 483 | 13.9,19.24,88.73,602.9,0.07991,1 484 | 13.47,14.06,87.32,546.3,0.1071,1 485 | 13.7,17.64,87.76,571.1,0.0995,1 486 | 15.73,11.28,102.8,747.2,0.1043,1 487 | 12.45,16.41,82.85,476.7,0.09514,1 488 | 14.64,16.85,94.21,666.0,0.08641,1 489 | 19.44,18.82,128.1,1167.0,0.1089,0 490 | 11.68,16.17,75.49,420.5,0.1128,1 491 | 16.69,20.2,107.1,857.6,0.07497,0 492 | 12.25,22.44,78.18,466.5,0.08192,1 493 | 17.85,13.23,114.6,992.1,0.07838,1 494 | 18.01,20.56,118.4,1007.0,0.1001,0 495 | 12.46,12.83,78.83,477.3,0.07372,1 496 | 13.16,20.54,84.06,538.7,0.07335,1 497 | 14.87,20.21,96.12,680.9,0.09587,1 498 | 12.65,18.17,82.69,485.6,0.1076,1 499 | 12.47,17.31,80.45,480.1,0.08928,1 500 | 18.49,17.52,121.3,1068.0,0.1012,0 501 | 20.59,21.24,137.8,1320.0,0.1085,0 502 | 15.04,16.74,98.73,689.4,0.09883,1 503 | 13.82,24.49,92.33,595.9,0.1162,0 504 | 12.54,16.32,81.25,476.3,0.1158,1 505 | 23.09,19.83,152.1,1682.0,0.09342,0 506 | 9.268,12.87,61.49,248.7,0.1634,1 507 | 9.676,13.14,64.12,272.5,0.1255,1 508 | 12.22,20.04,79.47,453.1,0.1096,1 509 | 11.06,17.12,71.25,366.5,0.1194,1 510 | 16.3,15.7,104.7,819.8,0.09427,1 511 | 15.46,23.95,103.8,731.3,0.1183,0 512 | 11.74,14.69,76.31,426.0,0.08099,1 513 | 14.81,14.7,94.66,680.7,0.08472,1 514 | 13.4,20.52,88.64,556.7,0.1106,0 515 | 14.58,13.66,94.29,658.8,0.09832,1 516 | 15.05,19.07,97.26,701.9,0.09215,0 517 | 11.34,18.61,72.76,391.2,0.1049,1 518 | 18.31,20.58,120.8,1052.0,0.1068,0 519 | 19.89,20.26,130.5,1214.0,0.1037,0 520 | 12.88,18.22,84.45,493.1,0.1218,1 521 | 12.75,16.7,82.51,493.8,0.1125,1 522 | 9.295,13.9,59.96,257.8,0.1371,1 523 | 24.63,21.6,165.5,1841.0,0.103,0 524 | 11.26,19.83,71.3,388.1,0.08511,1 525 | 13.71,18.68,88.73,571.0,0.09916,1 526 | 9.847,15.68,63.0,293.2,0.09492,1 527 | 8.571,13.1,54.53,221.3,0.1036,1 528 | 13.46,18.75,87.44,551.1,0.1075,1 529 | 12.34,12.27,78.94,468.5,0.09003,1 530 | 13.94,13.17,90.31,594.2,0.1248,1 531 | 12.07,13.44,77.83,445.2,0.11,1 532 | 11.75,17.56,75.89,422.9,0.1073,1 533 | 11.67,20.02,75.21,416.2,0.1016,1 534 | 13.68,16.33,87.76,575.5,0.09277,1 535 | 20.47,20.67,134.7,1299.0,0.09156,0 536 | 10.96,17.62,70.79,365.6,0.09687,1 537 | 20.55,20.86,137.8,1308.0,0.1046,0 538 | 14.27,22.55,93.77,629.8,0.1038,0 539 | 11.69,24.44,76.37,406.4,0.1236,1 540 | 7.729,25.49,47.98,178.8,0.08098,1 541 | 7.691,25.44,48.34,170.4,0.08668,1 542 | 11.54,14.44,74.65,402.9,0.09984,1 543 | 14.47,24.99,95.81,656.4,0.08837,1 544 | 14.74,25.42,94.7,668.6,0.08275,1 545 | 13.21,28.06,84.88,538.4,0.08671,1 546 | 13.87,20.7,89.77,584.8,0.09578,1 547 | 13.62,23.23,87.19,573.2,0.09246,1 548 | 10.32,16.35,65.31,324.9,0.09434,1 549 | 10.26,16.58,65.85,320.8,0.08877,1 550 | 9.683,19.34,61.05,285.7,0.08491,1 551 | 10.82,24.21,68.89,361.6,0.08192,1 552 | 10.86,21.48,68.51,360.5,0.07431,1 553 | 11.13,22.44,71.49,378.4,0.09566,1 554 | 12.77,29.43,81.35,507.9,0.08276,1 555 | 9.333,21.94,59.01,264.0,0.0924,1 556 | 12.88,28.92,82.5,514.3,0.08123,1 557 | 10.29,27.61,65.67,321.4,0.0903,1 558 | 10.16,19.59,64.73,311.7,0.1003,1 559 | 9.423,27.88,59.26,271.3,0.08123,1 560 | 14.59,22.68,96.39,657.1,0.08473,1 561 | 11.51,23.93,74.52,403.5,0.09261,1 562 | 14.05,27.15,91.38,600.4,0.09929,1 563 | 11.2,29.37,70.67,386.0,0.07449,1 564 | 15.22,30.62,103.4,716.9,0.1048,0 565 | 20.92,25.09,143.0,1347.0,0.1099,0 566 | 21.56,22.39,142.0,1479.0,0.111,0 567 | 20.13,28.25,131.2,1261.0,0.0978,0 568 | 16.6,28.08,108.3,858.1,0.08455,0 569 | 20.6,29.33,140.1,1265.0,0.1178,0 570 | 7.76,24.54,47.92,181.0,0.05263,1 571 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ML_from_Scratch 2 | Trying to implement basic ml algorithms from scratch in python. I have also made videos explaining these algorithms... 3 | 4 | ## Gradient Descent 5 | [![IMAGE ALT TEXT HERE](https://i.ytimg.com/vi/36zkIAAUcZ4/mqdefault.jpg)](https://youtu.be/36zkIAAUcZ4) 6 | [![IMAGE ALT TEXT HERE](https://i.ytimg.com/vi/41BiBUZbg9U/mqdefault.jpg)](https://youtu.be/41BiBUZbg9U) 7 | 8 | 9 | ## Linear Regression 10 | [![IMAGE ALT TEXT HERE](https://i.ytimg.com/vi/fnDO1s4fzi4/mqdefault.jpg)](https://youtu.be/fnDO1s4fzi4) 11 | 12 | ## Logistic Regression 13 | [![IMAGE ALT TEXT HERE](https://i.ytimg.com/vi/NtjAeXppomA/mqdefault.jpg)](https://youtu.be/NtjAeXppomA) 14 | 15 | ## Stochastic Gradient Descent 16 | [![IMAGE ALT TEXT HERE](https://i.ytimg.com/vi/V8InSDYHG4s/mqdefault.jpg)](https://youtu.be/V8InSDYHG4s) 17 | 18 | ## KNN 19 | [![IMAGE ALT TEXT HERE](https://i.ytimg.com/vi/0RwM2BaLNkE/mqdefault.jpg)](https://youtu.be/0RwM2BaLNkE) 20 | 21 | ## K-means 22 | [![IMAGE ALT TEXT HERE](https://i.ytimg.com/vi/IB9WfafBmjk/mqdefault.jpg)](https://youtu.be/IB9WfafBmjk) 23 | 24 | ## Decision Tree Classification 25 | [![IMAGE ALT TEXT HERE](https://i.ytimg.com/vi/ZVR2Way4nwQ/mqdefault.jpg)](https://youtu.be/ZVR2Way4nwQ) 26 | [![IMAGE ALT TEXT HERE](https://i.ytimg.com/vi/sgQAhG5Q7iY/mqdefault.jpg)](https://youtu.be/sgQAhG5Q7iY) 27 | 28 | 29 | ## Decision Tree Regression 30 | [![IMAGE ALT TEXT HERE](https://i.ytimg.com/vi/UhY5vPfQIrA/mqdefault.jpg)](https://youtu.be/UhY5vPfQIrA) 31 | [![IMAGE ALT TEXT HERE](https://i.ytimg.com/vi/P2ZB8c5Ha1Q/mqdefault.jpg)](https://youtu.be/P2ZB8c5Ha1Q) 32 | 33 | ## Naive Bayes Classification 34 | [![IMAGE ALT TEXT HERE](https://i.ytimg.com/vi/lFJbZ6LVxN8/mqdefault.jpg)](https://youtu.be/lFJbZ6LVxN8) 35 | [![IMAGE ALT TEXT HERE](https://i.ytimg.com/vi/3I8oX3OUL6I/mqdefault.jpg)](https://youtu.be/3I8oX3OUL6I) 36 | 37 | ## Data source 38 | - airfoil_noise_data.csv (converted from the .dat file available at https://archive.ics.uci.edu/ml/datasets/airfoil+self-noise) 39 | 40 | Donor: 41 | Dr Roberto Lopez 42 | robertolopez '@' intelnics.com 43 | Intelnics 44 | 45 | Creators: 46 | Thomas F. Brooks, D. Stuart Pope and Michael A. Marcolini 47 | NASA 48 | 49 | - Breast_cancer_data.csv (taken from https://www.kaggle.com/merishnasuwal/breast-cancer-prediction-dataset) 50 | -------------------------------------------------------------------------------- /decision tree classification.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Import tools" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 1, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import numpy as np\n", 17 | "import pandas as pd" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "## Get the data" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": 2, 30 | "metadata": { 31 | "scrolled": false 32 | }, 33 | "outputs": [ 34 | { 35 | "data": { 36 | "text/html": [ 37 | "
\n", 38 | "\n", 51 | "\n", 52 | " \n", 53 | " \n", 54 | " \n", 55 | " \n", 56 | " \n", 57 | " \n", 58 | " \n", 59 | " \n", 60 | " \n", 61 | " \n", 62 | " \n", 63 | " \n", 64 | " \n", 65 | " \n", 66 | " \n", 67 | " \n", 68 | " \n", 69 | " \n", 70 | " \n", 71 | " \n", 72 | " \n", 73 | " \n", 74 | " \n", 75 | " \n", 76 | " \n", 77 | " \n", 78 | " \n", 79 | " \n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | " \n", 87 | " \n", 88 | " \n", 89 | " \n", 90 | " \n", 91 | " \n", 92 | " \n", 93 | " \n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | " \n", 123 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 144 | "
sepal_lengthsepal_widthpetal_lengthpetal_widthtype
05.13.51.40.20
14.93.01.40.20
24.73.21.30.20
34.63.11.50.20
45.03.61.40.20
55.43.91.70.40
64.63.41.40.30
75.03.41.50.20
84.42.91.40.20
94.93.11.50.10
\n", 145 | "
" 146 | ], 147 | "text/plain": [ 148 | " sepal_length sepal_width petal_length petal_width type\n", 149 | "0 5.1 3.5 1.4 0.2 0\n", 150 | "1 4.9 3.0 1.4 0.2 0\n", 151 | "2 4.7 3.2 1.3 0.2 0\n", 152 | "3 4.6 3.1 1.5 0.2 0\n", 153 | "4 5.0 3.6 1.4 0.2 0\n", 154 | "5 5.4 3.9 1.7 0.4 0\n", 155 | "6 4.6 3.4 1.4 0.3 0\n", 156 | "7 5.0 3.4 1.5 0.2 0\n", 157 | "8 4.4 2.9 1.4 0.2 0\n", 158 | "9 4.9 3.1 1.5 0.1 0" 159 | ] 160 | }, 161 | "execution_count": 2, 162 | "metadata": {}, 163 | "output_type": "execute_result" 164 | } 165 | ], 166 | "source": [ 167 | "col_names = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'type']\n", 168 | "data = pd.read_csv(\"iris.csv\", skiprows=1, header=None, names=col_names)\n", 169 | "data.head(10)" 170 | ] 171 | }, 172 | { 173 | "cell_type": "markdown", 174 | "metadata": {}, 175 | "source": [ 176 | "## Node class" 177 | ] 178 | }, 179 | { 180 | "cell_type": "code", 181 | "execution_count": 3, 182 | "metadata": {}, 183 | "outputs": [], 184 | "source": [ 185 | "class Node():\n", 186 | " def __init__(self, feature_index=None, threshold=None, left=None, right=None, info_gain=None, value=None):\n", 187 | " ''' constructor ''' \n", 188 | " \n", 189 | " # for decision node\n", 190 | " self.feature_index = feature_index\n", 191 | " self.threshold = threshold\n", 192 | " self.left = left\n", 193 | " self.right = right\n", 194 | " self.info_gain = info_gain\n", 195 | " \n", 196 | " # for leaf node\n", 197 | " self.value = value" 198 | ] 199 | }, 200 | { 201 | "cell_type": "markdown", 202 | "metadata": {}, 203 | "source": [ 204 | "## Tree class" 205 | ] 206 | }, 207 | { 208 | "cell_type": "code", 209 | "execution_count": 4, 210 | "metadata": {}, 211 | "outputs": [], 212 | "source": [ 213 | "class DecisionTreeClassifier():\n", 214 | " def __init__(self, min_samples_split=2, max_depth=2):\n", 215 | " ''' constructor '''\n", 216 | " \n", 217 | " # initialize the root of the tree \n", 218 | " self.root = None\n", 219 | " \n", 220 | " # stopping conditions\n", 221 | " self.min_samples_split = min_samples_split\n", 222 | " self.max_depth = max_depth\n", 223 | " \n", 224 | " def build_tree(self, dataset, curr_depth=0):\n", 225 | " ''' recursive function to build the tree ''' \n", 226 | " \n", 227 | " X, Y = dataset[:,:-1], dataset[:,-1]\n", 228 | " num_samples, num_features = np.shape(X)\n", 229 | " \n", 230 | " # split until stopping conditions are met\n", 231 | " if num_samples>=self.min_samples_split and curr_depth<=self.max_depth:\n", 232 | " # find the best split\n", 233 | " best_split = self.get_best_split(dataset, num_samples, num_features)\n", 234 | " # check if information gain is positive\n", 235 | " if best_split[\"info_gain\"]>0:\n", 236 | " # recur left\n", 237 | " left_subtree = self.build_tree(best_split[\"dataset_left\"], curr_depth+1)\n", 238 | " # recur right\n", 239 | " right_subtree = self.build_tree(best_split[\"dataset_right\"], curr_depth+1)\n", 240 | " # return decision node\n", 241 | " return Node(best_split[\"feature_index\"], best_split[\"threshold\"], \n", 242 | " left_subtree, right_subtree, best_split[\"info_gain\"])\n", 243 | " \n", 244 | " # compute leaf node\n", 245 | " leaf_value = self.calculate_leaf_value(Y)\n", 246 | " # return leaf node\n", 247 | " return Node(value=leaf_value)\n", 248 | " \n", 249 | " def get_best_split(self, dataset, num_samples, num_features):\n", 250 | " ''' function to find the best split '''\n", 251 | " \n", 252 | " # dictionary to store the best split\n", 253 | " best_split = {}\n", 254 | " max_info_gain = -float(\"inf\")\n", 255 | " \n", 256 | " # loop over all the features\n", 257 | " for feature_index in range(num_features):\n", 258 | " feature_values = dataset[:, feature_index]\n", 259 | " possible_thresholds = np.unique(feature_values)\n", 260 | " # loop over all the feature values present in the data\n", 261 | " for threshold in possible_thresholds:\n", 262 | " # get current split\n", 263 | " dataset_left, dataset_right = self.split(dataset, feature_index, threshold)\n", 264 | " # check if childs are not null\n", 265 | " if len(dataset_left)>0 and len(dataset_right)>0:\n", 266 | " y, left_y, right_y = dataset[:, -1], dataset_left[:, -1], dataset_right[:, -1]\n", 267 | " # compute information gain\n", 268 | " curr_info_gain = self.information_gain(y, left_y, right_y, \"gini\")\n", 269 | " # update the best split if needed\n", 270 | " if curr_info_gain>max_info_gain:\n", 271 | " best_split[\"feature_index\"] = feature_index\n", 272 | " best_split[\"threshold\"] = threshold\n", 273 | " best_split[\"dataset_left\"] = dataset_left\n", 274 | " best_split[\"dataset_right\"] = dataset_right\n", 275 | " best_split[\"info_gain\"] = curr_info_gain\n", 276 | " max_info_gain = curr_info_gain\n", 277 | " \n", 278 | " # return best split\n", 279 | " return best_split\n", 280 | " \n", 281 | " def split(self, dataset, feature_index, threshold):\n", 282 | " ''' function to split the data '''\n", 283 | " \n", 284 | " dataset_left = np.array([row for row in dataset if row[feature_index]<=threshold])\n", 285 | " dataset_right = np.array([row for row in dataset if row[feature_index]>threshold])\n", 286 | " return dataset_left, dataset_right\n", 287 | " \n", 288 | " def information_gain(self, parent, l_child, r_child, mode=\"entropy\"):\n", 289 | " ''' function to compute information gain '''\n", 290 | " \n", 291 | " weight_l = len(l_child) / len(parent)\n", 292 | " weight_r = len(r_child) / len(parent)\n", 293 | " if mode==\"gini\":\n", 294 | " gain = self.gini_index(parent) - (weight_l*self.gini_index(l_child) + weight_r*self.gini_index(r_child))\n", 295 | " else:\n", 296 | " gain = self.entropy(parent) - (weight_l*self.entropy(l_child) + weight_r*self.entropy(r_child))\n", 297 | " return gain\n", 298 | " \n", 299 | " def entropy(self, y):\n", 300 | " ''' function to compute entropy '''\n", 301 | " \n", 302 | " class_labels = np.unique(y)\n", 303 | " entropy = 0\n", 304 | " for cls in class_labels:\n", 305 | " p_cls = len(y[y == cls]) / len(y)\n", 306 | " entropy += -p_cls * np.log2(p_cls)\n", 307 | " return entropy\n", 308 | " \n", 309 | " def gini_index(self, y):\n", 310 | " ''' function to compute gini index '''\n", 311 | " \n", 312 | " class_labels = np.unique(y)\n", 313 | " gini = 0\n", 314 | " for cls in class_labels:\n", 315 | " p_cls = len(y[y == cls]) / len(y)\n", 316 | " gini += p_cls**2\n", 317 | " return 1 - gini\n", 318 | " \n", 319 | " def calculate_leaf_value(self, Y):\n", 320 | " ''' function to compute leaf node '''\n", 321 | " \n", 322 | " Y = list(Y)\n", 323 | " return max(Y, key=Y.count)\n", 324 | " \n", 325 | " def print_tree(self, tree=None, indent=\" \"):\n", 326 | " ''' function to print the tree '''\n", 327 | " \n", 328 | " if not tree:\n", 329 | " tree = self.root\n", 330 | "\n", 331 | " if tree.value is not None:\n", 332 | " print(tree.value)\n", 333 | "\n", 334 | " else:\n", 335 | " print(\"X_\"+str(tree.feature_index), \"<=\", tree.threshold, \"?\", tree.info_gain)\n", 336 | " print(\"%sleft:\" % (indent), end=\"\")\n", 337 | " self.print_tree(tree.left, indent + indent)\n", 338 | " print(\"%sright:\" % (indent), end=\"\")\n", 339 | " self.print_tree(tree.right, indent + indent)\n", 340 | " \n", 341 | " def fit(self, X, Y):\n", 342 | " ''' function to train the tree '''\n", 343 | " \n", 344 | " dataset = np.concatenate((X, Y), axis=1)\n", 345 | " self.root = self.build_tree(dataset)\n", 346 | " \n", 347 | " def predict(self, X):\n", 348 | " ''' function to predict new dataset '''\n", 349 | " \n", 350 | " preditions = [self.make_prediction(x, self.root) for x in X]\n", 351 | " return preditions\n", 352 | " \n", 353 | " def make_prediction(self, x, tree):\n", 354 | " ''' function to predict a single data point '''\n", 355 | " \n", 356 | " if tree.value!=None: return tree.value\n", 357 | " feature_val = x[tree.feature_index]\n", 358 | " if feature_val<=tree.threshold:\n", 359 | " return self.make_prediction(x, tree.left)\n", 360 | " else:\n", 361 | " return self.make_prediction(x, tree.right)" 362 | ] 363 | }, 364 | { 365 | "cell_type": "markdown", 366 | "metadata": {}, 367 | "source": [ 368 | "## Train-Test split" 369 | ] 370 | }, 371 | { 372 | "cell_type": "code", 373 | "execution_count": 5, 374 | "metadata": {}, 375 | "outputs": [], 376 | "source": [ 377 | "X = data.iloc[:, :-1].values\n", 378 | "Y = data.iloc[:, -1].values.reshape(-1,1)\n", 379 | "from sklearn.model_selection import train_test_split\n", 380 | "X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=.2, random_state=41)" 381 | ] 382 | }, 383 | { 384 | "cell_type": "markdown", 385 | "metadata": {}, 386 | "source": [ 387 | "## Fit the model" 388 | ] 389 | }, 390 | { 391 | "cell_type": "code", 392 | "execution_count": 6, 393 | "metadata": {}, 394 | "outputs": [ 395 | { 396 | "name": "stdout", 397 | "output_type": "stream", 398 | "text": [ 399 | "X_2 <= 1.9 ? 0.33741385372714494\n", 400 | " left:0.0\n", 401 | " right:X_3 <= 1.5 ? 0.427106638180289\n", 402 | " left:X_2 <= 4.9 ? 0.05124653739612173\n", 403 | " left:1.0\n", 404 | " right:2.0\n", 405 | " right:X_2 <= 5.0 ? 0.019631171921475288\n", 406 | " left:X_1 <= 2.8 ? 0.20833333333333334\n", 407 | " left:2.0\n", 408 | " right:1.0\n", 409 | " right:2.0\n" 410 | ] 411 | } 412 | ], 413 | "source": [ 414 | "classifier = DecisionTreeClassifier(min_samples_split=3, max_depth=3)\n", 415 | "classifier.fit(X_train,Y_train)\n", 416 | "classifier.print_tree()" 417 | ] 418 | }, 419 | { 420 | "cell_type": "markdown", 421 | "metadata": {}, 422 | "source": [ 423 | "## Test the model" 424 | ] 425 | }, 426 | { 427 | "cell_type": "code", 428 | "execution_count": 7, 429 | "metadata": {}, 430 | "outputs": [ 431 | { 432 | "data": { 433 | "text/plain": [ 434 | "0.9333333333333333" 435 | ] 436 | }, 437 | "execution_count": 7, 438 | "metadata": {}, 439 | "output_type": "execute_result" 440 | } 441 | ], 442 | "source": [ 443 | "Y_pred = classifier.predict(X_test) \n", 444 | "from sklearn.metrics import accuracy_score\n", 445 | "accuracy_score(Y_test, Y_pred)" 446 | ] 447 | } 448 | ], 449 | "metadata": { 450 | "kernelspec": { 451 | "display_name": "Python 3", 452 | "language": "python", 453 | "name": "python3" 454 | }, 455 | "language_info": { 456 | "codemirror_mode": { 457 | "name": "ipython", 458 | "version": 3 459 | }, 460 | "file_extension": ".py", 461 | "mimetype": "text/x-python", 462 | "name": "python", 463 | "nbconvert_exporter": "python", 464 | "pygments_lexer": "ipython3", 465 | "version": "3.8.5" 466 | } 467 | }, 468 | "nbformat": 4, 469 | "nbformat_minor": 4 470 | } 471 | -------------------------------------------------------------------------------- /decision tree regression.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Import tools" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 1, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import numpy as np\n", 17 | "import pandas as pd" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "## Get the data" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": 2, 30 | "metadata": {}, 31 | "outputs": [ 32 | { 33 | "data": { 34 | "text/html": [ 35 | "
\n", 36 | "\n", 49 | "\n", 50 | " \n", 51 | " \n", 52 | " \n", 53 | " \n", 54 | " \n", 55 | " \n", 56 | " \n", 57 | " \n", 58 | " \n", 59 | " \n", 60 | " \n", 61 | " \n", 62 | " \n", 63 | " \n", 64 | " \n", 65 | " \n", 66 | " \n", 67 | " \n", 68 | " \n", 69 | " \n", 70 | " \n", 71 | " \n", 72 | " \n", 73 | " \n", 74 | " \n", 75 | " \n", 76 | " \n", 77 | " \n", 78 | " \n", 79 | " \n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | " \n", 87 | " \n", 88 | " \n", 89 | " \n", 90 | " \n", 91 | " \n", 92 | " \n", 93 | " \n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | "
x0x1x2x3x4y
08000.00.304871.30.002663126.201
110000.00.304871.30.002663125.201
212500.00.304871.30.002663125.951
316000.00.304871.30.002663127.591
420000.00.304871.30.002663127.461
\n", 109 | "
" 110 | ], 111 | "text/plain": [ 112 | " x0 x1 x2 x3 x4 y\n", 113 | "0 800 0.0 0.3048 71.3 0.002663 126.201\n", 114 | "1 1000 0.0 0.3048 71.3 0.002663 125.201\n", 115 | "2 1250 0.0 0.3048 71.3 0.002663 125.951\n", 116 | "3 1600 0.0 0.3048 71.3 0.002663 127.591\n", 117 | "4 2000 0.0 0.3048 71.3 0.002663 127.461" 118 | ] 119 | }, 120 | "execution_count": 2, 121 | "metadata": {}, 122 | "output_type": "execute_result" 123 | } 124 | ], 125 | "source": [ 126 | "data = pd.read_csv(\"airfoil_noise_data.csv\")\n", 127 | "data.head(5)" 128 | ] 129 | }, 130 | { 131 | "cell_type": "markdown", 132 | "metadata": {}, 133 | "source": [ 134 | "## Node class" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": 3, 140 | "metadata": {}, 141 | "outputs": [], 142 | "source": [ 143 | "class Node():\n", 144 | " def __init__(self, feature_index=None, threshold=None, left=None, right=None, var_red=None, value=None):\n", 145 | " ''' constructor ''' \n", 146 | " \n", 147 | " # for decision node\n", 148 | " self.feature_index = feature_index\n", 149 | " self.threshold = threshold\n", 150 | " self.left = left\n", 151 | " self.right = right\n", 152 | " self.var_red = var_red\n", 153 | " \n", 154 | " # for leaf node\n", 155 | " self.value = value" 156 | ] 157 | }, 158 | { 159 | "cell_type": "markdown", 160 | "metadata": {}, 161 | "source": [ 162 | "## Tree class" 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": 4, 168 | "metadata": {}, 169 | "outputs": [], 170 | "source": [ 171 | "class DecisionTreeRegressor():\n", 172 | " def __init__(self, min_samples_split=2, max_depth=2):\n", 173 | " ''' constructor '''\n", 174 | " \n", 175 | " # initialize the root of the tree \n", 176 | " self.root = None\n", 177 | " \n", 178 | " # stopping conditions\n", 179 | " self.min_samples_split = min_samples_split\n", 180 | " self.max_depth = max_depth\n", 181 | " \n", 182 | " def build_tree(self, dataset, curr_depth=0):\n", 183 | " ''' recursive function to build the tree '''\n", 184 | " \n", 185 | " X, Y = dataset[:,:-1], dataset[:,-1]\n", 186 | " num_samples, num_features = np.shape(X)\n", 187 | " best_split = {}\n", 188 | " # split until stopping conditions are met\n", 189 | " if num_samples>=self.min_samples_split and curr_depth<=self.max_depth:\n", 190 | " # find the best split\n", 191 | " best_split = self.get_best_split(dataset, num_samples, num_features)\n", 192 | " # check if information gain is positive\n", 193 | " if best_split[\"var_red\"]>0:\n", 194 | " # recur left\n", 195 | " left_subtree = self.build_tree(best_split[\"dataset_left\"], curr_depth+1)\n", 196 | " # recur right\n", 197 | " right_subtree = self.build_tree(best_split[\"dataset_right\"], curr_depth+1)\n", 198 | " # return decision node\n", 199 | " return Node(best_split[\"feature_index\"], best_split[\"threshold\"], \n", 200 | " left_subtree, right_subtree, best_split[\"var_red\"])\n", 201 | " \n", 202 | " # compute leaf node\n", 203 | " leaf_value = self.calculate_leaf_value(Y)\n", 204 | " # return leaf node\n", 205 | " return Node(value=leaf_value)\n", 206 | " \n", 207 | " def get_best_split(self, dataset, num_samples, num_features):\n", 208 | " ''' function to find the best split '''\n", 209 | " \n", 210 | " # dictionary to store the best split\n", 211 | " best_split = {}\n", 212 | " max_var_red = -float(\"inf\")\n", 213 | " # loop over all the features\n", 214 | " for feature_index in range(num_features):\n", 215 | " feature_values = dataset[:, feature_index]\n", 216 | " possible_thresholds = np.unique(feature_values)\n", 217 | " # loop over all the feature values present in the data\n", 218 | " for threshold in possible_thresholds:\n", 219 | " # get current split\n", 220 | " dataset_left, dataset_right = self.split(dataset, feature_index, threshold)\n", 221 | " # check if childs are not null\n", 222 | " if len(dataset_left)>0 and len(dataset_right)>0:\n", 223 | " y, left_y, right_y = dataset[:, -1], dataset_left[:, -1], dataset_right[:, -1]\n", 224 | " # compute information gain\n", 225 | " curr_var_red = self.variance_reduction(y, left_y, right_y)\n", 226 | " # update the best split if needed\n", 227 | " if curr_var_red>max_var_red:\n", 228 | " best_split[\"feature_index\"] = feature_index\n", 229 | " best_split[\"threshold\"] = threshold\n", 230 | " best_split[\"dataset_left\"] = dataset_left\n", 231 | " best_split[\"dataset_right\"] = dataset_right\n", 232 | " best_split[\"var_red\"] = curr_var_red\n", 233 | " max_var_red = curr_var_red\n", 234 | " \n", 235 | " # return best split\n", 236 | " return best_split\n", 237 | " \n", 238 | " def split(self, dataset, feature_index, threshold):\n", 239 | " ''' function to split the data '''\n", 240 | " \n", 241 | " dataset_left = np.array([row for row in dataset if row[feature_index]<=threshold])\n", 242 | " dataset_right = np.array([row for row in dataset if row[feature_index]>threshold])\n", 243 | " return dataset_left, dataset_right\n", 244 | " \n", 245 | " def variance_reduction(self, parent, l_child, r_child):\n", 246 | " ''' function to compute variance reduction '''\n", 247 | " \n", 248 | " weight_l = len(l_child) / len(parent)\n", 249 | " weight_r = len(r_child) / len(parent)\n", 250 | " reduction = np.var(parent) - (weight_l * np.var(l_child) + weight_r * np.var(r_child))\n", 251 | " return reduction\n", 252 | " \n", 253 | " def calculate_leaf_value(self, Y):\n", 254 | " ''' function to compute leaf node '''\n", 255 | " \n", 256 | " val = np.mean(Y)\n", 257 | " return val\n", 258 | " \n", 259 | " def print_tree(self, tree=None, indent=\" \"):\n", 260 | " ''' function to print the tree '''\n", 261 | " \n", 262 | " if not tree:\n", 263 | " tree = self.root\n", 264 | "\n", 265 | " if tree.value is not None:\n", 266 | " print(tree.value)\n", 267 | "\n", 268 | " else:\n", 269 | " print(\"X_\"+str(tree.feature_index), \"<=\", tree.threshold, \"?\", tree.var_red)\n", 270 | " print(\"%sleft:\" % (indent), end=\"\")\n", 271 | " self.print_tree(tree.left, indent + indent)\n", 272 | " print(\"%sright:\" % (indent), end=\"\")\n", 273 | " self.print_tree(tree.right, indent + indent)\n", 274 | " \n", 275 | " def fit(self, X, Y):\n", 276 | " ''' function to train the tree '''\n", 277 | " \n", 278 | " dataset = np.concatenate((X, Y), axis=1)\n", 279 | " self.root = self.build_tree(dataset)\n", 280 | " \n", 281 | " def make_prediction(self, x, tree):\n", 282 | " ''' function to predict new dataset '''\n", 283 | " \n", 284 | " if tree.value!=None: return tree.value\n", 285 | " feature_val = x[tree.feature_index]\n", 286 | " if feature_val<=tree.threshold:\n", 287 | " return self.make_prediction(x, tree.left)\n", 288 | " else:\n", 289 | " return self.make_prediction(x, tree.right)\n", 290 | " \n", 291 | " def predict(self, X):\n", 292 | " ''' function to predict a single data point '''\n", 293 | " \n", 294 | " preditions = [self.make_prediction(x, self.root) for x in X]\n", 295 | " return preditions" 296 | ] 297 | }, 298 | { 299 | "cell_type": "markdown", 300 | "metadata": {}, 301 | "source": [ 302 | "## Train-Test split" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": 5, 308 | "metadata": {}, 309 | "outputs": [], 310 | "source": [ 311 | "X = data.iloc[:, :-1].values\n", 312 | "Y = data.iloc[:, -1].values.reshape(-1,1)\n", 313 | "from sklearn.model_selection import train_test_split\n", 314 | "X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=.2, random_state=41)" 315 | ] 316 | }, 317 | { 318 | "cell_type": "markdown", 319 | "metadata": {}, 320 | "source": [ 321 | "## Fit the model" 322 | ] 323 | }, 324 | { 325 | "cell_type": "code", 326 | "execution_count": 6, 327 | "metadata": {}, 328 | "outputs": [ 329 | { 330 | "name": "stdout", 331 | "output_type": "stream", 332 | "text": [ 333 | "X_0 <= 3150.0 ? 7.132048702017748\n", 334 | " left:X_4 <= 0.033779199999999995 ? 3.5903305690676675\n", 335 | " left:X_3 <= 55.5 ? 1.1789899981318328\n", 336 | " left:X_4 <= 0.00251435 ? 1.614396721819876\n", 337 | " left:128.9919833333333\n", 338 | " right:125.90953579676673\n", 339 | " right:X_1 <= 15.4 ? 2.2342245360792994\n", 340 | " left:129.39160280373832\n", 341 | " right:123.80422222222222\n", 342 | " right:X_0 <= 1250.0 ? 9.970884020498875\n", 343 | " left:X_4 <= 0.0483159 ? 6.355275159824863\n", 344 | " left:124.38024528301887\n", 345 | " right:118.30039999999998\n", 346 | " right:X_3 <= 39.6 ? 5.036286657241022\n", 347 | " left:113.58091666666667\n", 348 | " right:118.07284615384614\n", 349 | " right:X_4 <= 0.00146332 ? 29.082992105065273\n", 350 | " left:X_0 <= 8000.0 ? 11.886497073996967\n", 351 | " left:X_2 <= 0.0508 ? 7.608945827689513\n", 352 | " left:134.04247500000002\n", 353 | " right:127.33581818181818\n", 354 | " right:X_4 <= 0.00076193 ? 10.622919322400815\n", 355 | " left:128.94078571428574\n", 356 | " right:122.4076875\n", 357 | " right:X_4 <= 0.022902799999999997 ? 5.638575922510647\n", 358 | " left:X_0 <= 6300.0 ? 5.985051045988911\n", 359 | " left:120.04740816326529\n", 360 | " right:114.67370491803278\n", 361 | " right:X_4 <= 0.0368233 ? 8.63874479304644\n", 362 | " left:113.83169565217393\n", 363 | " right:107.6395833333333\n" 364 | ] 365 | } 366 | ], 367 | "source": [ 368 | "regressor = DecisionTreeRegressor(min_samples_split=3, max_depth=3)\n", 369 | "regressor.fit(X_train,Y_train)\n", 370 | "regressor.print_tree()" 371 | ] 372 | }, 373 | { 374 | "cell_type": "markdown", 375 | "metadata": {}, 376 | "source": [ 377 | "## Test the model" 378 | ] 379 | }, 380 | { 381 | "cell_type": "code", 382 | "execution_count": 7, 383 | "metadata": {}, 384 | "outputs": [ 385 | { 386 | "data": { 387 | "text/plain": [ 388 | "4.851358097184457" 389 | ] 390 | }, 391 | "execution_count": 7, 392 | "metadata": {}, 393 | "output_type": "execute_result" 394 | } 395 | ], 396 | "source": [ 397 | "Y_pred = regressor.predict(X_test) \n", 398 | "from sklearn.metrics import mean_squared_error\n", 399 | "np.sqrt(mean_squared_error(Y_test, Y_pred))" 400 | ] 401 | } 402 | ], 403 | "metadata": { 404 | "kernelspec": { 405 | "display_name": "Python 3", 406 | "language": "python", 407 | "name": "python3" 408 | }, 409 | "language_info": { 410 | "codemirror_mode": { 411 | "name": "ipython", 412 | "version": 3 413 | }, 414 | "file_extension": ".py", 415 | "mimetype": "text/x-python", 416 | "name": "python", 417 | "nbconvert_exporter": "python", 418 | "pygments_lexer": "ipython3", 419 | "version": "3.8.5" 420 | } 421 | }, 422 | "nbformat": 4, 423 | "nbformat_minor": 4 424 | } 425 | -------------------------------------------------------------------------------- /linear regression.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Generating Fake Data" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 16, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "from sklearn.datasets.samples_generator import make_regression\n", 17 | "X, y = make_regression(n_samples=200, n_features=1, n_informative=1, noise=6, bias=30, random_state=200)\n", 18 | "m = 200" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "## Visualizing the Data" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": 25, 31 | "metadata": {}, 32 | "outputs": [ 33 | { 34 | "data": { 35 | "image/png": "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\n", 36 | "text/plain": [ 37 | "
" 38 | ] 39 | }, 40 | "metadata": {}, 41 | "output_type": "display_data" 42 | } 43 | ], 44 | "source": [ 45 | "from matplotlib import pyplot as plt\n", 46 | "plt.scatter(X,y, c = \"red\",alpha=.5, marker = 'o')\n", 47 | "plt.xlabel(\"X\")\n", 48 | "plt.ylabel(\"Y\")\n", 49 | "plt.show()" 50 | ] 51 | }, 52 | { 53 | "cell_type": "markdown", 54 | "metadata": {}, 55 | "source": [ 56 | "## Linear Model" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 18, 62 | "metadata": {}, 63 | "outputs": [], 64 | "source": [ 65 | "import numpy as np\n", 66 | "def h(X,w):\n", 67 | " return (w[1]*np.array(X[:,0])+w[0])" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "## Cost Function" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 19, 80 | "metadata": {}, 81 | "outputs": [], 82 | "source": [ 83 | "def cost(w,X,y):\n", 84 | " return (.5/m) * np.sum(np.square(h(X,w)-np.array(y)))" 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "## Gradient Descent " 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": 20, 97 | "metadata": {}, 98 | "outputs": [], 99 | "source": [ 100 | "def grad(w,X,y):\n", 101 | " g = [0]*2\n", 102 | " g[0] = (1/m) * np.sum(h(X,w)-np.array(y))\n", 103 | " g[1] = (1/m) * np.sum((h(X,w)-np.array(y))*np.array(X[:,0]))\n", 104 | " return g\n" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": 21, 110 | "metadata": {}, 111 | "outputs": [], 112 | "source": [ 113 | "def descent(w_new, w_prev, lr):\n", 114 | " print(w_prev)\n", 115 | " print(cost(w_prev,X,y))\n", 116 | " j=0\n", 117 | " while True:\n", 118 | " w_prev = w_new\n", 119 | " w0 = w_prev[0] - lr*grad(w_prev,X,y)[0]\n", 120 | " w1 = w_prev[1] - lr*grad(w_prev,X,y)[1]\n", 121 | " w_new = [w0, w1]\n", 122 | " print(w_new)\n", 123 | " print(cost(w_new,X,y))\n", 124 | " if (w_new[0]-w_prev[0])**2 + (w_new[1]-w_prev[1])**2 <= pow(10,-6):\n", 125 | " return w_new\n", 126 | " if j>500: \n", 127 | " return w_new\n", 128 | " j+=1 " 129 | ] 130 | }, 131 | { 132 | "cell_type": "markdown", 133 | "metadata": {}, 134 | "source": [ 135 | "## Initializing Parameters" 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": 22, 141 | "metadata": {}, 142 | "outputs": [], 143 | "source": [ 144 | "w = [0,-1]" 145 | ] 146 | }, 147 | { 148 | "cell_type": "markdown", 149 | "metadata": {}, 150 | "source": [ 151 | "## Training the Model" 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": 23, 157 | "metadata": {}, 158 | "outputs": [ 159 | { 160 | "name": "stdout", 161 | "output_type": "stream", 162 | "text": [ 163 | "[0, -1]\n", 164 | "540.5360663843456\n", 165 | "[3.0956308633447547, 0.11442770988081663]\n", 166 | "437.91139336428444\n", 167 | "[5.873446610978822, 1.1023454281382854]\n", 168 | "355.5039050187037\n", 169 | "[8.366165526017987, 1.9778657783247602]\n", 170 | "289.3267499184995\n", 171 | "[10.603129563187093, 2.753547324958939]\n", 172 | "236.1799750745718\n", 173 | "[12.610653489037027, 3.440564026385428]\n", 174 | "193.49509649539323\n", 175 | "[14.412337853388406, 4.048856351454087]\n", 176 | "159.2103901995911\n", 177 | "[16.0293495446536, 4.587266032213945]\n", 178 | "131.6708284668908\n", 179 | "[17.480673291820082, 5.063656213710697]\n", 180 | "109.54778810165583\n", 181 | "[18.7833371265594, 5.485018573380515]\n", 182 | "91.77462156224563\n", 183 | "[19.952614505935692, 5.857568814053481]\n", 184 | "77.49495508304668\n", 185 | "[21.002205515744066, 6.186831784078626]\n", 186 | "66.02119816099949\n", 187 | "[21.944399323224108, 6.4777173436470505]\n", 188 | "56.801246289923824\n", 189 | "[22.79021982273288, 6.734587976310905]\n", 190 | "49.39175789964725\n", 191 | "[23.549556216205993, 6.961319037445921]\n", 192 | "43.436706577550574\n", 193 | "[24.23128008944935, 7.1613524356181975]\n", 194 | "38.6501664442448\n", 195 | "[24.843350383306017, 7.337744457271138]\n", 196 | "34.802494555336104\n", 197 | "[25.39290751357782, 7.493208368754656]\n", 198 | "31.709239459080347\n", 199 | "[25.88635776349851, 7.630152361500887]\n", 200 | "29.22223761683571\n", 201 | "[26.329448955986066, 7.750713345236864]\n", 202 | "27.22246575546644\n", 203 | "[26.727338308440384, 7.85678703973609]\n", 204 | "25.614302554322332\n", 205 | "[27.084653279240058, 7.950054767051352]\n", 206 | "24.320921533807876\n", 207 | "[27.405546131200424, 8.032007302818467]\n", 208 | "23.280591944370723\n", 209 | "[27.69374286207346, 8.10396610651881]\n", 210 | "22.443708530267372\n", 211 | "[27.952587084793493, 8.167102216040767]\n", 212 | "21.77040640846802\n", 213 | "[28.1850793797893, 8.222453061042739]\n", 214 | "21.22864568158778\n", 215 | "[28.393912587566714, 8.270937422096216]\n", 216 | "20.792673176173675\n", 217 | "[28.581503461264624, 8.313368738022628]\n", 218 | "20.44178697219165\n", 219 | "[28.75002105541824, 8.350466941915155]\n", 220 | "20.159344055135406\n", 221 | "[28.901412188203544, 8.382868986773879]\n", 222 | "19.93196319200716\n", 223 | "[29.03742427951789, 8.411138204226754]\n", 224 | "19.74888457866804\n", 225 | "[29.159625835953786, 8.435772624233959]\n", 226 | "19.601455387770752\n", 227 | "[29.2694248256702, 8.45721236977788]\n", 228 | "19.482716431969585\n", 229 | "[29.368085161021078, 8.475846228144906]\n", 230 | "19.387070041859424\n", 231 | "[29.45674148426251, 8.492017489347575]\n", 232 | "19.310013179228125\n", 233 | "[29.536412431457247, 8.506029132372674]\n", 234 | "19.24792295396926\n", 235 | "[29.60801253158606, 8.518148431144402]\n", 236 | "19.19788424005612\n", 237 | "[29.672362881642048, 8.528611044246796]\n", 238 | "19.157551114830053\n", 239 | "[29.73020072393229, 8.537624645454327]\n", 240 | "19.125035474814123\n", 241 | "[29.782188038766204, 8.545372145882025]\n", 242 | "19.09881748922257\n", 243 | "[29.828919254015993, 8.552014553005522]\n", 244 | "19.077673602614112\n", 245 | "[29.87092816255075, 8.557693506843796]\n", 246 | "19.06061864154971\n", 247 | "[29.90869412914744, 8.562533529178292]\n", 248 | "19.046859257450855\n", 249 | "[29.942647660055936, 8.566644017743355]\n", 250 | "19.035756481849372\n", 251 | "[29.97317540084111, 8.57012101381262]\n", 252 | "19.026795607153897\n", 253 | "[30.000624621352255, 8.573048768478005]\n", 254 | "19.019561957024997\n", 255 | "[30.025307240597662, 8.57550113013079]\n", 256 | "19.013721392385282\n", 257 | "[30.047503438857856, 8.577542773171217]\n", 258 | "19.009004625587373\n", 259 | "[30.067464899489234, 8.579230285760998]\n", 260 | "19.005194597236063\n", 261 | "[30.085417718492856, 8.580613132462974]\n", 262 | "19.00211631637512\n", 263 | "[30.101565015998244, 8.581734505857439]\n", 264 | "18.99962868224005\n", 265 | "[30.11608928029284, 8.582632079662158]\n", 266 | "18.99761790019706\n", 267 | "[30.12915447187187, 8.583338674491873]\n", 268 | "18.995992180371438\n", 269 | "[30.14090791215345, 8.583882846154577]\n", 270 | "18.994677468461337\n", 271 | "[30.151481978966018, 8.584289405279359]\n", 272 | "18.993614007260764\n", 273 | "[30.160995628639302, 8.58457987608947]\n", 274 | "18.99275356682987\n", 275 | "[30.169555762489143, 8.584772901261081]\n", 276 | "18.992057212939287\n", 277 | "[30.177258453655917, 8.584884599031389]\n", 278 | "18.991493508895633\n", 279 | "[30.184190048614877, 8.584928878028586]\n", 280 | "18.991037066345022\n", 281 | "[30.190428156204195, 8.584917714681556]\n", 282 | "18.99066737713041\n", 283 | "[30.196042535696083, 8.584861397520429]\n", 284 | "18.99036787153328\n", 285 | "[30.201095894251807, 8.584768742193141]\n", 286 | "18.990125158892102\n", 287 | "[30.205644603039065, 8.58464728059093]\n", 288 | "18.989928415168315\n", 289 | "[30.20973934033721, 8.584503427091704]\n", 290 | "18.98976888893204\n", 291 | "[30.21342566910097, 8.58434262458882]\n", 292 | "18.98963950279431\n", 293 | "[30.216744555686475, 8.584169472669567]\n", 294 | "18.989534531782173\n", 295 | "[30.219732835755565, 8.58398784003826]\n", 296 | "18.9894493437512\n", 297 | "[30.22242363275721, 8.583800963039536]\n", 298 | "18.989380189826502\n", 299 | "[30.22484673383125, 8.583611531925033]\n", 300 | "18.989324035195228\n", 301 | "[30.227028927482966, 8.583421766317985]\n", 302 | "18.989278422451623\n", 303 | "[30.228994306931416, 8.583233481162887]\n", 304 | "18.98924136120799\n", 305 | "[30.23076454263459, 8.583048144298838]\n", 306 | "18.98921123890338\n", 307 | "[30.23235912713573, 8.582866926663364]\n", 308 | "18.98918674872298\n", 309 | "[30.233795595053294, 8.582690746016727]\n", 310 | "18.98916683133221\n", 311 | "[30.235089720748128, 8.582520304973011]\n", 312 | "18.989150627766747\n", 313 | "[30.23625569594233, 8.582356124032495]\n", 314 | "18.98913744133326\n", 315 | "[30.237306289331627, 8.582198570228412]\n", 316 | "18.989126706789886\n", 317 | "[30.238252990024396, 8.582047881929046]\n", 318 | "18.98911796540923\n", 319 | "[30.238252990024396, 8.582047881929046]\n" 320 | ] 321 | } 322 | ], 323 | "source": [ 324 | "w = descent(w,w,.1)\n", 325 | "print(w)" 326 | ] 327 | }, 328 | { 329 | "cell_type": "markdown", 330 | "metadata": {}, 331 | "source": [ 332 | "## Visualizing the Result" 333 | ] 334 | }, 335 | { 336 | "cell_type": "code", 337 | "execution_count": 24, 338 | "metadata": {}, 339 | "outputs": [ 340 | { 341 | "data": { 342 | "image/png": "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\n", 343 | "text/plain": [ 344 | "
" 345 | ] 346 | }, 347 | "metadata": {}, 348 | "output_type": "display_data" 349 | } 350 | ], 351 | "source": [ 352 | "def graph(formula, x_range): \n", 353 | " x = np.array(x_range) \n", 354 | " y = formula(x) \n", 355 | " plt.plot(x, y) \n", 356 | " \n", 357 | "def my_formula(x):\n", 358 | " return w[0]+w[1]*x\n", 359 | "\n", 360 | "plt.scatter(X,y, c = \"red\",alpha=.5, marker = 'o')\n", 361 | "graph(my_formula, range(-5,5))\n", 362 | "plt.xlabel('X')\n", 363 | "plt.ylabel('Y')\n", 364 | "plt.show()" 365 | ] 366 | } 367 | ], 368 | "metadata": { 369 | "kernelspec": { 370 | "display_name": "Python 3", 371 | "language": "python", 372 | "name": "python3" 373 | }, 374 | "language_info": { 375 | "codemirror_mode": { 376 | "name": "ipython", 377 | "version": 3 378 | }, 379 | "file_extension": ".py", 380 | "mimetype": "text/x-python", 381 | "name": "python", 382 | "nbconvert_exporter": "python", 383 | "pygments_lexer": "ipython3", 384 | "version": "3.6.5" 385 | } 386 | }, 387 | "nbformat": 4, 388 | "nbformat_minor": 2 389 | } 390 | -------------------------------------------------------------------------------- /logistic regression.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Creating Fake Data" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 26, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "from sklearn.datasets.samples_generator import make_blobs\n", 17 | "X, Y = make_blobs(n_samples=200, centers=2, n_features=2, cluster_std=5, random_state=11)\n", 18 | "m = 200" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "## Visualizing the Data" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": 28, 31 | "metadata": {}, 32 | "outputs": [ 33 | { 34 | "data": { 35 | "image/png": "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\n", 36 | "text/plain": [ 37 | "
" 38 | ] 39 | }, 40 | "metadata": {}, 41 | "output_type": "display_data" 42 | } 43 | ], 44 | "source": [ 45 | "from matplotlib import pyplot as plt\n", 46 | "from pandas import DataFrame \n", 47 | "df = DataFrame(dict(x=X[:,0], y=X[:,1], label=Y))\n", 48 | "colors = {0:'blue', 1:'orange'}\n", 49 | "fig, ax = plt.subplots()\n", 50 | "grouped = df.groupby('label')\n", 51 | "for key, group in grouped:\n", 52 | " group.plot(ax=ax, kind='scatter', x='x', y='y', label=key, color=colors[key])\n", 53 | "plt.xlabel('X_0')\n", 54 | "plt.ylabel('X_1')\n", 55 | "plt.show()" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "## Logistic Model" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 6, 68 | "metadata": {}, 69 | "outputs": [], 70 | "source": [ 71 | "import numpy as np\n", 72 | "def sigmoid(z):\n", 73 | " return 1 / (1 + np.exp(-z))" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 7, 79 | "metadata": {}, 80 | "outputs": [], 81 | "source": [ 82 | "def hx(w,X):\n", 83 | " z = np.array(w[0] + w[1]*np.array(X[:,0]) + w[2]*np.array(X[:,1]))\n", 84 | " return sigmoid(z)" 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "## Cost Function - Binary Cross Entropy " 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": 8, 97 | "metadata": {}, 98 | "outputs": [], 99 | "source": [ 100 | "def cost(w, X, Y):\n", 101 | " y_pred = hx(w,X)\n", 102 | " return -1 * sum(Y*np.log(y_pred) + (1-Y)*np.log(1-y_pred))" 103 | ] 104 | }, 105 | { 106 | "cell_type": "markdown", 107 | "metadata": {}, 108 | "source": [ 109 | "## Gradient Descent" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": 9, 115 | "metadata": {}, 116 | "outputs": [], 117 | "source": [ 118 | "def grad(w, X, Y):\n", 119 | " y_pred = hx(w,X)\n", 120 | " g = [0]*3\n", 121 | " g[0] = -1 * sum(Y*(1-y_pred) - (1-Y)*y_pred)\n", 122 | " g[1] = -1 * sum(Y*(1-y_pred)*X[:,0] - (1-Y)*y_pred*X[:,0])\n", 123 | " g[2] = -1 * sum(Y*(1-y_pred)*X[:,1] - (1-Y)*y_pred*X[:,1])\n", 124 | " return g" 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": 37, 130 | "metadata": {}, 131 | "outputs": [], 132 | "source": [ 133 | "def descent(w_new, w_prev, lr):\n", 134 | " print(w_prev)\n", 135 | " print(cost(w_prev, X, Y))\n", 136 | " j=0\n", 137 | " while True:\n", 138 | " w_prev = w_new\n", 139 | " w0 = w_prev[0] - lr*grad(w_prev, X, Y)[0]\n", 140 | " w1 = w_prev[1] - lr*grad(w_prev, X, Y)[1]\n", 141 | " w2 = w_prev[2] - lr*grad(w_prev, X, Y)[2]\n", 142 | " w_new = [w0, w1, w2]\n", 143 | " print(w_new)\n", 144 | " print(cost(w_new, X, Y))\n", 145 | " if (w_new[0]-w_prev[0])**2 + (w_new[1]-w_prev[1])**2 + (w_new[2]-w_prev[2])**2 100: \n", 149 | " return w_new\n", 150 | " j+=1" 151 | ] 152 | }, 153 | { 154 | "cell_type": "markdown", 155 | "metadata": {}, 156 | "source": [ 157 | "## Initializing Parameters" 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": 38, 163 | "metadata": {}, 164 | "outputs": [], 165 | "source": [ 166 | "w=[1,1,1] " 167 | ] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "metadata": {}, 172 | "source": [ 173 | "## Training the Model" 174 | ] 175 | }, 176 | { 177 | "cell_type": "code", 178 | "execution_count": 39, 179 | "metadata": {}, 180 | "outputs": [ 181 | { 182 | "name": "stdout", 183 | "output_type": "stream", 184 | "text": [ 185 | "[1, 1, 1]\n", 186 | "126.96627984087802\n", 187 | "[1.2539422898588644, -0.5512710240837779, 1.1843328109648115]\n", 188 | "112.81815690482537\n", 189 | "[1.2400289717256012, 1.3365539538600526, 1.3041857280167006]\n", 190 | "168.5749357223354\n", 191 | "[1.496038556709955, -0.26091766794801896, 1.498589948744304]\n", 192 | "75.77036936925771\n", 193 | "[1.552998152697941, 0.5805338886016641, 1.2059963033700993]\n", 194 | "67.88063552779857\n", 195 | "[1.7129970823802407, -0.12884219161477717, 0.9205552719943874]\n", 196 | "49.631255078140065\n", 197 | "[1.721522374547689, 0.8081464107255731, 0.784948881261807]\n", 198 | "84.65164447415044\n", 199 | "[1.9318934810214365, -0.5853214217947893, 0.9260582355386137]\n", 200 | "137.02236299684375\n", 201 | "[1.792209433897121, 2.259519445068961, 1.8717281361304319]\n", 202 | "296.375960910099\n", 203 | "[2.0717704014100984, 0.4671501798576154, 2.2375086018139254]\n", 204 | "96.21982855549399\n", 205 | "[2.2275891867070294, 0.17556932949773574, 1.7757719140648793]\n", 206 | "66.93614685472798\n", 207 | "[2.34635073219192, 0.10042351859759649, 1.3377088708014218]\n", 208 | "47.88369966457564\n", 209 | "[2.420814222298708, 0.2006649466226462, 0.9803329461122527]\n", 210 | "35.74059972551982\n", 211 | "[2.47109414690982, 0.15761477718705647, 0.7206148121331153]\n", 212 | "31.156227520259954\n", 213 | "[2.4669494157236738, 0.33368915465087157, 0.6530382051207929]\n", 214 | "31.825794017269445\n", 215 | "[2.5018185122166057, 0.052068234061564855, 0.5947139224875355]\n", 216 | "37.13648828690444\n", 217 | "[2.4168290256808196, 0.8618663362335011, 0.8721726092434906]\n", 218 | "77.31322559093016\n", 219 | "[2.596954895024072, -0.39576768312727784, 0.9305031886901464]\n", 220 | "97.53803980330012\n", 221 | "[2.4680716616586964, 1.8009384856190926, 1.4733863829082396]\n", 222 | "210.1650208652238\n", 223 | "[2.7256313646387795, 0.10398042243284711, 1.7582377785757068]\n", 224 | "60.930800473556\n", 225 | "[2.8139079434551295, 0.18042029298994794, 1.356581836503274]\n", 226 | "44.87910324512945\n", 227 | "[2.8764378665294585, 0.18788023515027294, 1.0240956114450044]\n", 228 | "35.1115767203633\n", 229 | "[2.9004091563475756, 0.25373283853477424, 0.8052448292395792]\n", 230 | "31.203934623682823\n", 231 | "[2.905564316215357, 0.23573784244902107, 0.6972405539065145]\n", 232 | "30.64594404630533\n", 233 | "[2.884978695284491, 0.3156866373830539, 0.7013654663287641]\n", 234 | "30.87299094573297\n", 235 | "[2.8899757309235032, 0.18571374355707734, 0.662108112619276]\n", 236 | "31.58765075793203\n", 237 | "[2.8456086105455767, 0.44695414312741255, 0.7472822400464028]\n", 238 | "34.997339236852504\n", 239 | "[2.8946903864992204, 0.0311385451581056, 0.652724208526957]\n", 240 | "41.16553917784135\n", 241 | "[2.78333314375564, 1.0205125031757631, 0.9858502424130702]\n", 242 | "90.41042650497221\n", 243 | "[2.970171901127539, -0.2925927602835001, 1.054289078329687]\n", 244 | "77.28627608547319\n", 245 | "[2.8765338440725268, 1.3870481637289969, 1.2593201244024514]\n", 246 | "137.884699579421\n", 247 | "[3.096205693561861, -0.09815951484676533, 1.3875700666825428]\n", 248 | "55.28433950652438\n", 249 | "[3.091222620686947, 0.691357878366354, 1.1851902704372872]\n", 250 | "54.56897648020144\n", 251 | "[3.197031648206172, 0.04853253754001363, 0.9522363399023503]\n", 252 | "38.879877723561194\n", 253 | "[3.152849114551307, 0.6705086356955698, 0.9042855300104767]\n", 254 | "47.42326651334623\n", 255 | "[3.249401718635574, -0.05586144519042935, 0.7968950006624693]\n", 256 | "50.77734982683568\n", 257 | "[3.1265348460183477, 1.2297186855362119, 1.1081714720550426]\n", 258 | "111.36985561835434\n", 259 | "[3.326563756861511, -0.1791741101134301, 1.2218462740483753]\n", 260 | "62.108694704750796\n", 261 | "[3.269128921912794, 1.0293263482837012, 1.2008084141382773]\n", 262 | "82.99082598516479\n", 263 | "[3.433600163161756, -0.10416961202267583, 1.1426909126167342]\n", 264 | "53.969099415361306\n", 265 | "[3.372434392083106, 0.9606133194736919, 1.1258764505552485]\n", 266 | "73.24867011604414\n", 267 | "[3.5227671344926526, -0.10541269443776047, 1.0639829014706683]\n", 268 | "54.95877911862518\n", 269 | "[3.4402314176940667, 1.0678781146572354, 1.1359656744505753]\n", 270 | "84.39209613357035\n", 271 | "[3.6053162123525917, -0.1094419475498285, 1.1193961332548408]\n", 272 | "55.78053131843188\n", 273 | "[3.5284998867311446, 1.035838685329749, 1.1603344516799623]\n", 274 | "79.31512100875807\n", 275 | "[3.6850794814765253, -0.0823331021711422, 1.117327385696941]\n", 276 | "53.365825253435844\n", 277 | "[3.6094245208717335, 0.990136688364013, 1.1479057502919368]\n", 278 | "73.00073094363131\n", 279 | "[3.7550639240710013, -0.06190456364194685, 1.0874826200950347]\n", 280 | "51.85370536629623\n", 281 | "[3.6740149106228186, 0.9863883933259856, 1.1383256238195103]\n", 282 | "71.6077027550773\n", 283 | "[3.816365454730692, -0.053415680920452235, 1.079972647866281]\n", 284 | "51.512482717018116\n", 285 | "[3.7321415001226725, 0.9874518828741854, 1.1419582058166857]\n", 286 | "70.91147940312463\n", 287 | "[3.8721953817202945, -0.040975086743274325, 1.0817922008147334]\n", 288 | "50.68840558905084\n", 289 | "[3.7880511473342113, 0.9676622239349191, 1.1410140920986547]\n", 290 | "68.11602429098141\n", 291 | "[3.9218160093807857, -0.02032252700940551, 1.069864113475001]\n", 292 | "49.12965800771219\n", 293 | "[3.8372555826614154, 0.9397003151318558, 1.1301065005574003]\n", 294 | "64.66526827228455\n", 295 | "[3.963079147188273, 0.0015189750142303726, 1.048002481200122]\n", 296 | "47.55953959619178\n", 297 | "[3.8768575558853064, 0.9161026456599739, 1.116464165382025]\n", 298 | "61.870753988367085\n", 299 | "[3.995752432150913, 0.019597576030487285, 1.027414752411626]\n", 300 | "46.36190019402692\n", 301 | "[3.907745460549524, 0.89829389197684, 1.1055063163003485]\n", 302 | "59.82357707095895\n", 303 | "[4.0211666051250194, 0.03440304270300665, 1.0117153695411087]\n", 304 | "45.42762114954028\n", 305 | "[3.932061436494771, 0.8820448670623741, 1.0967233693735197]\n", 306 | "58.07265242127726\n", 307 | "[4.040538211472588, 0.0486222507940266, 0.9980600115598323]\n", 308 | "44.528626105329884\n", 309 | "[3.95104075816509, 0.8635822178845587, 1.087464778932447]\n", 310 | "56.25191093140636\n", 311 | "[4.0542064633885655, 0.06390897971924736, 0.9830845369826282]\n", 312 | "43.560297250359895\n", 313 | "[3.9647146116297285, 0.8419896969170714, 1.0762339319145042]\n", 314 | "54.28859760963312\n", 315 | "[4.061974777022511, 0.08010117719043697, 0.9658476947904583]\n", 316 | "42.55609321933739\n", 317 | "[3.9726570293297416, 0.8185528342778258, 1.0632653646122094]\n", 318 | "52.30757518813522\n", 319 | "[4.063741047353516, 0.09591304118161548, 0.9474917553090927]\n", 320 | "41.60869408164448\n", 321 | "[3.9746698824165576, 0.7955306511635729, 1.0497944865210715]\n", 322 | "50.49160062072334\n", 323 | "[4.0598875620346835, 0.10973094543337403, 0.929938489713735]\n", 324 | "40.807102034142616\n", 325 | "[3.9710681877912237, 0.7754202550430537, 1.0373138237663093]\n", 326 | "49.006821287773285\n", 327 | "[4.051367062032833, 0.120083598318384, 0.9149680408447317]\n", 328 | "40.21376802733146\n", 329 | "[3.9626934207233138, 0.7605664236412619, 1.027175552319945]\n", 330 | "47.97972673492794\n", 331 | "[4.03960146305846, 0.1258626202000106, 0.9038701158750538]\n", 332 | "39.8665848590012\n", 333 | "[3.9508175989838605, 0.7529117846030396, 1.0204483002710898]\n", 334 | "47.49986495259877\n", 335 | "[4.026319016314264, 0.12633822832598507, 0.8975122703008471]\n", 336 | "39.79309105387893\n", 337 | "[3.937022647315148, 0.7539702241394387, 1.0179583095352271]\n", 338 | "47.64232237902202\n", 339 | "[4.013431600037268, 0.12097838008325779, 0.8966869188055052]\n", 340 | "40.03060914399324\n", 341 | "[3.9231193858382776, 0.7650499798316024, 1.0204780871163988]\n", 342 | "48.50370516914084\n", 343 | "[4.0030116224672625, 0.10920033650354244, 0.9025652832558652]\n", 344 | "40.647028942768124\n", 345 | "[3.911168807082645, 0.7874617085157639, 1.0289496414232508]\n", 346 | "50.233655133405684\n", 347 | "[3.9973475854531766, 0.09037455328475408, 0.9170124097333662]\n", 348 | "41.74920834355003\n", 349 | "[3.9036347048532614, 0.8219989928942072, 1.0444815131818708]\n", 350 | "53.00756665023323\n", 351 | "[3.998896442510712, 0.06491278493707686, 0.9421306486550264]\n", 352 | "43.414481126056494\n", 353 | "[3.903578932273919, 0.8658652317559935, 1.0673333907773224]\n", 354 | "56.743118405663786\n", 355 | "[4.009605120891904, 0.03790132000571389, 0.9771595777097101]\n", 356 | "45.367245465512056\n", 357 | "[3.9142374607656074, 0.9053571447819756, 1.0933903406414625]\n", 358 | "60.26445149748922\n", 359 | "[4.028982704706953, 0.022311918251399665, 1.0115367561804436]\n", 360 | "46.56452396428107\n", 361 | "[3.936118279261484, 0.9161216408470005, 1.1107981056735687]\n", 362 | "61.119030592288695\n", 363 | "[4.05221859760455, 0.029367074818002936, 1.0249045662087954]\n", 364 | "46.03001820966252\n", 365 | "[3.962804479787527, 0.890313219168536, 1.1082732172211933]\n", 366 | "58.54793332826261\n", 367 | "[4.071694739617031, 0.05576987084898566, 1.0076561457699287]\n", 368 | "44.146310350361176\n", 369 | "[3.9843650919995444, 0.8441134205516451, 1.087132296857637]\n", 370 | "54.38313567139385\n", 371 | "[4.081221437775141, 0.08935078570508614, 0.9713207459960232]\n", 372 | "42.00179619891018\n", 373 | "[3.9945804561228613, 0.7946114356824799, 1.058305857789166]\n", 374 | "50.363531876210516\n", 375 | "[4.078719695444127, 0.11976411937445264, 0.9330027012706759]\n", 376 | "40.284159514532284\n", 377 | "[3.992398365094767, 0.7520453654158086, 1.0315755035230465]\n", 378 | "47.27452627208367\n", 379 | "[4.065870596044042, 0.14186053507189011, 0.9025860178561832]\n", 380 | "39.138492702670455\n", 381 | "[3.9799787694173245, 0.7210735715432988, 1.0111931600659616]\n", 382 | "45.255334753917104\n", 383 | "[4.0460976445817955, 0.15448991706397763, 0.8819752531296552]\n", 384 | "38.48142071458852\n", 385 | "[3.960514974560398, 0.7030948526309135, 0.9977984989102618]\n", 386 | "44.1983732970012\n", 387 | "[4.022890960756249, 0.1583065776331426, 0.8696992149881329]\n", 388 | "38.21770810120381\n", 389 | "[3.937085053426291, 0.6982103483166531, 0.9909832248890901]\n", 390 | "43.98944447469072\n", 391 | "[3.937085053426291, 0.6982103483166531, 0.9909832248890901]\n" 392 | ] 393 | } 394 | ], 395 | "source": [ 396 | "w = descent(w,w,.0099)\n", 397 | "print(w)" 398 | ] 399 | }, 400 | { 401 | "cell_type": "markdown", 402 | "metadata": {}, 403 | "source": [ 404 | "## Visualizing the Result" 405 | ] 406 | }, 407 | { 408 | "cell_type": "code", 409 | "execution_count": 40, 410 | "metadata": {}, 411 | "outputs": [ 412 | { 413 | "data": { 414 | "image/png": "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\n", 415 | "text/plain": [ 416 | "
" 417 | ] 418 | }, 419 | "metadata": {}, 420 | "output_type": "display_data" 421 | } 422 | ], 423 | "source": [ 424 | "def graph(formula, x_range): \n", 425 | " x = np.array(x_range) \n", 426 | " y = formula(x) \n", 427 | " plt.plot(x, y) \n", 428 | " \n", 429 | "def my_formula(x):\n", 430 | " return (-w[0]-w[1]*x)/w[2]\n", 431 | "\n", 432 | "from matplotlib import pyplot as plt\n", 433 | "from pandas import DataFrame \n", 434 | "df = DataFrame(dict(x=X[:,0], y=X[:,1], label=Y))\n", 435 | "colors = {0:'blue', 1:'orange'}\n", 436 | "fig, ax = plt.subplots()\n", 437 | "grouped = df.groupby('label')\n", 438 | "for key, group in grouped:\n", 439 | " group.plot(ax=ax, kind='scatter', x='x', y='y', label=key, color=colors[key])\n", 440 | "graph(my_formula, range(-20,15))\n", 441 | "plt.xlabel('X_0')\n", 442 | "plt.ylabel('X_1')\n", 443 | "plt.show()" 444 | ] 445 | } 446 | ], 447 | "metadata": { 448 | "kernelspec": { 449 | "display_name": "Python 3", 450 | "language": "python", 451 | "name": "python3" 452 | }, 453 | "language_info": { 454 | "codemirror_mode": { 455 | "name": "ipython", 456 | "version": 3 457 | }, 458 | "file_extension": ".py", 459 | "mimetype": "text/x-python", 460 | "name": "python", 461 | "nbconvert_exporter": "python", 462 | "pygments_lexer": "ipython3", 463 | "version": "3.6.5" 464 | } 465 | }, 466 | "nbformat": 4, 467 | "nbformat_minor": 2 468 | } 469 | -------------------------------------------------------------------------------- /sgd.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Creating Fake Data" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 1, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import numpy as np\n", 17 | "from sklearn.utils import shuffle\n", 18 | "from sklearn.datasets.samples_generator import make_blobs\n", 19 | "X, Y = make_blobs(n_samples=300, centers=2, n_features=2, cluster_std=5, random_state=11)" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "## Visualizing the Data" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 3, 32 | "metadata": {}, 33 | "outputs": [ 34 | { 35 | "data": { 36 | "image/png": "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\n", 37 | "text/plain": [ 38 | "
" 39 | ] 40 | }, 41 | "metadata": {}, 42 | "output_type": "display_data" 43 | } 44 | ], 45 | "source": [ 46 | "from matplotlib import pyplot as plt\n", 47 | "from pandas import DataFrame \n", 48 | "df = DataFrame(dict(x=X[:,0], y=X[:,1], label=Y))\n", 49 | "colors = {0:'blue', 1:'orange'}\n", 50 | "fig, ax = plt.subplots()\n", 51 | "grouped = df.groupby('label')\n", 52 | "for key, group in grouped:\n", 53 | " group.plot(ax=ax, kind='scatter', x='x', y='y', label=key, color=colors[key])\n", 54 | "plt.xlabel('X_1')\n", 55 | "plt.ylabel('X_2')\n", 56 | "plt.show()" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "## Splitting into batches" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 4, 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [ 72 | "def next_batch(X, Y, batch_size):\n", 73 | " for i in np.arange(0, X.shape[0], batch_size):\n", 74 | " yield (X[i:i + batch_size], Y[i:i + batch_size])" 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": {}, 80 | "source": [ 81 | "## Adding column of 1's " 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 5, 87 | "metadata": {}, 88 | "outputs": [ 89 | { 90 | "data": { 91 | "text/plain": [ 92 | "(300, 3)" 93 | ] 94 | }, 95 | "execution_count": 5, 96 | "metadata": {}, 97 | "output_type": "execute_result" 98 | } 99 | ], 100 | "source": [ 101 | "X = np.c_[np.ones((X.shape[0])), X]\n", 102 | "X.shape" 103 | ] 104 | }, 105 | { 106 | "cell_type": "markdown", 107 | "metadata": {}, 108 | "source": [ 109 | "## Logistic Model" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": 6, 115 | "metadata": {}, 116 | "outputs": [], 117 | "source": [ 118 | "import numpy as np\n", 119 | "def sigmoid(z):\n", 120 | " return 1 / (1 + np.exp(-z))" 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": 7, 126 | "metadata": {}, 127 | "outputs": [], 128 | "source": [ 129 | "def hx(W,X):\n", 130 | " return sigmoid(np.dot(X,W))" 131 | ] 132 | }, 133 | { 134 | "cell_type": "markdown", 135 | "metadata": {}, 136 | "source": [ 137 | "## Cost Function - Binary Cross Entropy " 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": 8, 143 | "metadata": {}, 144 | "outputs": [], 145 | "source": [ 146 | "def cost(W, X, Y):\n", 147 | " y_pred = hx(W,X)\n", 148 | " return -1 * sum(Y*np.log(y_pred) + (1-Y)*np.log(1-y_pred))" 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "metadata": {}, 154 | "source": [ 155 | "## Stochastic Gradient Descent" 156 | ] 157 | }, 158 | { 159 | "cell_type": "code", 160 | "execution_count": 9, 161 | "metadata": {}, 162 | "outputs": [], 163 | "source": [ 164 | "def grad(W, X, Y):\n", 165 | " y_pred = hx(W,X)\n", 166 | " A = (Y*(1-y_pred) - (1-Y)*y_pred)\n", 167 | " g = -1* np.dot(A.T,X)\n", 168 | " return g" 169 | ] 170 | }, 171 | { 172 | "cell_type": "code", 173 | "execution_count": 10, 174 | "metadata": {}, 175 | "outputs": [], 176 | "source": [ 177 | "def sgd(W_new, W_prev, lr, batch_size, epochs):\n", 178 | " X_, Y_ = shuffle(X, Y, random_state=0)\n", 179 | " for e in range(epochs):\n", 180 | " epoch_loss = []\n", 181 | " X_, Y_ = shuffle(X_, Y_, random_state=0)\n", 182 | " for (batchX, batchY) in next_batch(X_, Y_, batch_size):\n", 183 | " W_prev = W_new\n", 184 | " epoch_loss.append(cost(W_prev, batchX, batchY))\n", 185 | " gradients = grad(W_prev, batchX, batchY)\n", 186 | " W_new = W_prev - lr*gradients\n", 187 | " print(np.average(epoch_loss))\n", 188 | " return W_new" 189 | ] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "metadata": {}, 194 | "source": [ 195 | "## Initializing Weights & Bias" 196 | ] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "execution_count": 11, 201 | "metadata": {}, 202 | "outputs": [ 203 | { 204 | "data": { 205 | "text/plain": [ 206 | "(3,)" 207 | ] 208 | }, 209 | "execution_count": 11, 210 | "metadata": {}, 211 | "output_type": "execute_result" 212 | } 213 | ], 214 | "source": [ 215 | "W = np.random.uniform(size=(X.shape[1],))\n", 216 | "W.shape" 217 | ] 218 | }, 219 | { 220 | "cell_type": "markdown", 221 | "metadata": {}, 222 | "source": [ 223 | "## Training the Model" 224 | ] 225 | }, 226 | { 227 | "cell_type": "code", 228 | "execution_count": 12, 229 | "metadata": {}, 230 | "outputs": [ 231 | { 232 | "name": "stdout", 233 | "output_type": "stream", 234 | "text": [ 235 | "[0.79618896 0.4163837 0.42391672]\n", 236 | "6.277384446178855\n", 237 | "5.743854541290189\n", 238 | "5.639645113634937\n", 239 | "5.470853335391083\n", 240 | "5.667962099033007\n", 241 | "5.28981499238036\n", 242 | "5.271342725834096\n", 243 | "5.060368761481374\n", 244 | "5.446976524735743\n", 245 | "5.066447704414417\n", 246 | "5.09547652563199\n", 247 | "5.027047324020139\n", 248 | "5.231413878163542\n", 249 | "4.988553649645022\n", 250 | "5.045966239495252\n", 251 | "5.114093205881277\n", 252 | "5.24313649711587\n", 253 | "5.3309800879511595\n", 254 | "5.2369933729138705\n", 255 | "4.931357222546931\n", 256 | "5.141072913940974\n", 257 | "4.865177946360237\n", 258 | "5.159259956251705\n", 259 | "4.9850013574989935\n", 260 | "5.075992543432262\n", 261 | "5.257537980731875\n", 262 | "5.15220734911969\n", 263 | "5.376113028226739\n", 264 | "5.01790696023796\n", 265 | "4.91743150129637\n", 266 | "5.155592756181093\n", 267 | "4.778496875740468\n", 268 | "5.170830308497642\n", 269 | "4.982057737386109\n", 270 | "5.065383224896023\n", 271 | "5.130301783329287\n", 272 | "5.0560422794900335\n", 273 | "4.751542045996459\n", 274 | "5.044836198314092\n", 275 | "5.200065208594642\n", 276 | "5.285956700133218\n", 277 | "4.69607623817095\n", 278 | "5.1110131343684895\n", 279 | "4.929261653440459\n", 280 | "5.508577234972032\n", 281 | "4.9295442093408335\n", 282 | "5.35853341436791\n", 283 | "5.109882297828997\n", 284 | "5.268900506923824\n", 285 | "5.0553568625861995\n", 286 | "5.127108057053507\n", 287 | "5.256180863878795\n", 288 | "5.2017470229439295\n", 289 | "5.29706022610866\n", 290 | "4.842578732589242\n", 291 | "5.216497984078021\n", 292 | "5.167172158840554\n", 293 | "5.030913544155235\n", 294 | "4.9208154561894215\n", 295 | "5.0286895579435775\n", 296 | "5.254927983516582\n", 297 | "5.01657084246088\n", 298 | "4.902782163580072\n", 299 | "4.952060238428389\n", 300 | "4.9191214387250035\n", 301 | "5.027098170280329\n", 302 | "5.077946337475286\n", 303 | "4.880098287861289\n", 304 | "4.944972140093644\n", 305 | "5.052666303168795\n", 306 | "5.081615975832211\n", 307 | "5.182569862898558\n", 308 | "4.9697239615921625\n", 309 | "5.056706134894904\n", 310 | "5.110368058329958\n", 311 | "4.996883358551884\n", 312 | "4.989696640078847\n", 313 | "4.858898302441649\n", 314 | "4.930715531754518\n", 315 | "5.009314794537656\n", 316 | "5.127984153485331\n", 317 | "5.0231049124602825\n", 318 | "5.254008279820028\n", 319 | "5.014073801135062\n", 320 | "4.97986671455312\n", 321 | "5.05243719762335\n", 322 | "5.0420997708089415\n", 323 | "5.069451589063102\n", 324 | "5.150257226697879\n", 325 | "5.164400634677876\n", 326 | "5.039134823534483\n", 327 | "4.9883474157043795\n", 328 | "5.132433782589542\n", 329 | "4.891167385232467\n", 330 | "5.062085674381252\n", 331 | "5.2087055067642165\n", 332 | "4.955120478076216\n", 333 | "4.88214965225135\n", 334 | "4.935119155279668\n", 335 | "5.4527388101645755\n", 336 | "4.902647474574163\n", 337 | "4.973218626980669\n", 338 | "4.969125747240431\n", 339 | "5.034819845305565\n", 340 | "5.11158072777152\n", 341 | "5.052709686640736\n", 342 | "4.968840505649011\n", 343 | "5.088612053925859\n", 344 | "4.915818444090352\n", 345 | "5.093157727293972\n", 346 | "5.033660011718062\n", 347 | "5.223412724166921\n", 348 | "5.1077816665230475\n", 349 | "5.135494856877415\n", 350 | "4.989777059244171\n", 351 | "5.165527490515357\n", 352 | "5.327764783138228\n", 353 | "5.019080784749545\n", 354 | "5.0239554594473805\n", 355 | "5.026682139880581\n", 356 | "5.159710856114193\n", 357 | "5.027795318281852\n", 358 | "4.988648104694423\n", 359 | "5.012928309587274\n", 360 | "5.081666714554431\n", 361 | "5.272117622609143\n", 362 | "4.851869972177484\n", 363 | "4.956969286562633\n", 364 | "5.025160410234134\n", 365 | "4.993677569943672\n", 366 | "5.099870584911604\n", 367 | "5.096181311604027\n", 368 | "5.236923964162504\n", 369 | "4.903674873885619\n", 370 | "5.075807820064275\n", 371 | "4.701673307737802\n", 372 | "5.299083765240716\n", 373 | "5.112201692629844\n", 374 | "5.057198863500682\n", 375 | "5.213612968874003\n", 376 | "5.1198465312517225\n", 377 | "4.928097399784619\n", 378 | "4.991964359552881\n", 379 | "4.994824548764347\n", 380 | "5.049272339126923\n", 381 | "4.942713247937617\n", 382 | "4.91913758023255\n", 383 | "5.43143326229052\n", 384 | "5.116114463071936\n", 385 | "4.9625898877661445\n", 386 | "5.042137105313292\n", 387 | "5.157805681662321\n", 388 | "5.04896325685934\n", 389 | "5.018982423826876\n", 390 | "5.185034061711793\n", 391 | "5.032465453425752\n", 392 | "4.897108003638827\n", 393 | "4.95421678149162\n", 394 | "5.259006286037971\n", 395 | "5.182717981721985\n", 396 | "4.884826442197778\n", 397 | "5.156842877561891\n", 398 | "5.047645060816286\n", 399 | "5.050121866311711\n", 400 | "4.869794749038038\n", 401 | "4.9957190876138835\n", 402 | "5.022988953794398\n", 403 | "5.002839753440677\n", 404 | "4.881319490767778\n", 405 | "5.055591006717888\n", 406 | "5.015670050297785\n", 407 | "5.013392499945725\n", 408 | "4.989724363452584\n", 409 | "4.880412359751283\n", 410 | "5.416224099805669\n", 411 | "5.2867392415724135\n", 412 | "5.11414942585176\n", 413 | "5.079966239068073\n", 414 | "4.925427043815789\n", 415 | "5.145176957835869\n", 416 | "5.130160451160554\n", 417 | "5.024814422423505\n", 418 | "4.958769936817604\n", 419 | "4.81843182784822\n", 420 | "5.34842232805925\n", 421 | "5.279335054775109\n", 422 | "5.107921381756868\n", 423 | "5.15079791674754\n", 424 | "5.096406330816437\n", 425 | "5.00585692466524\n", 426 | "5.200218860079871\n", 427 | "4.96229644142354\n", 428 | "4.937523034036624\n", 429 | "5.174090668819386\n", 430 | "5.1400977102309175\n", 431 | "5.1319926651455186\n", 432 | "5.048127875476851\n", 433 | "5.416048064604175\n", 434 | "5.057120736099771\n", 435 | "4.864273959307718\n", 436 | "[2.38150361 0.22263106 0.53666744]\n" 437 | ] 438 | } 439 | ], 440 | "source": [ 441 | "print(W)\n", 442 | "W = sgd(W, W, .009, 32, 200)\n", 443 | "print(W)" 444 | ] 445 | }, 446 | { 447 | "cell_type": "markdown", 448 | "metadata": {}, 449 | "source": [ 450 | "## Visualizing the Result" 451 | ] 452 | }, 453 | { 454 | "cell_type": "code", 455 | "execution_count": 13, 456 | "metadata": {}, 457 | "outputs": [ 458 | { 459 | "data": { 460 | "image/png": "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\n", 461 | "text/plain": [ 462 | "
" 463 | ] 464 | }, 465 | "metadata": {}, 466 | "output_type": "display_data" 467 | } 468 | ], 469 | "source": [ 470 | "def graph(formula, x_range): \n", 471 | " x = np.array(x_range) \n", 472 | " y = formula(x) \n", 473 | " plt.plot(x, y) \n", 474 | " \n", 475 | "def my_formula(x):\n", 476 | " return (-W[0]-W[1]*x)/W[2]\n", 477 | "\n", 478 | "from matplotlib import pyplot as plt\n", 479 | "from pandas import DataFrame \n", 480 | "df = DataFrame(dict(x=X[:,1], y=X[:,2], label=Y))\n", 481 | "colors = {0:'blue', 1:'orange'}\n", 482 | "fig, ax = plt.subplots()\n", 483 | "grouped = df.groupby('label')\n", 484 | "for key, group in grouped:\n", 485 | " group.plot(ax=ax, kind='scatter', x='x', y='y', label=key, color=colors[key])\n", 486 | "graph(my_formula, range(-20,15))\n", 487 | "plt.xlabel('X_1')\n", 488 | "plt.ylabel('X_2')\n", 489 | "plt.show()" 490 | ] 491 | } 492 | ], 493 | "metadata": { 494 | "kernelspec": { 495 | "display_name": "Python 3", 496 | "language": "python", 497 | "name": "python3" 498 | }, 499 | "language_info": { 500 | "codemirror_mode": { 501 | "name": "ipython", 502 | "version": 3 503 | }, 504 | "file_extension": ".py", 505 | "mimetype": "text/x-python", 506 | "name": "python", 507 | "nbconvert_exporter": "python", 508 | "pygments_lexer": "ipython3", 509 | "version": "3.6.5" 510 | } 511 | }, 512 | "nbformat": 4, 513 | "nbformat_minor": 2 514 | } 515 | --------------------------------------------------------------------------------