File size: 50,367 Bytes
8938d1b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "ename": "ModuleNotFoundError",
     "evalue": "No module named 'numpy'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mModuleNotFoundError\u001b[0m                       Traceback (most recent call last)",
      "\u001b[1;32m/Users/johnnydevriese/projects/jupyter/cs229-scratchpad.ipynb Cell 1'\u001b[0m in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> <a href='vscode-notebook-cell:/Users/johnnydevriese/projects/jupyter/cs229-scratchpad.ipynb#ch0000000?line=0'>1</a>\u001b[0m \u001b[39mimport\u001b[39;00m \u001b[39mnumpy\u001b[39;00m \u001b[39mas\u001b[39;00m \u001b[39mnp\u001b[39;00m\n\u001b[1;32m      <a href='vscode-notebook-cell:/Users/johnnydevriese/projects/jupyter/cs229-scratchpad.ipynb#ch0000000?line=2'>3</a>\u001b[0m x \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39marray([\u001b[39m1\u001b[39m, \u001b[39m2\u001b[39m, \u001b[39m3\u001b[39m])\n\u001b[1;32m      <a href='vscode-notebook-cell:/Users/johnnydevriese/projects/jupyter/cs229-scratchpad.ipynb#ch0000000?line=3'>4</a>\u001b[0m y \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39marray([\u001b[39m4\u001b[39m, \u001b[39m5\u001b[39m, \u001b[39m6\u001b[39m])\n",
      "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'numpy'"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "x = np.array([1, 2, 3])\n",
    "y = np.array([4, 5, 6])\n",
    "\n",
    "print(x.size)\n",
    "k = 5\n",
    "for k in range(k+1):\n",
    "    print(k)\n",
    "    foo = np.power(x[1], k)\n",
    "\n",
    "# todo: need to build a matrix \n",
    "x[1] ** np.arange(k)\n",
    "\n",
    "\n",
    "# polyn = np.array([1, np.power(x[0], )])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[8.41470985e-01 1.00000000e+00 1.00000000e+00 1.00000000e+00\n",
      "  1.00000000e+00 1.00000000e+00 1.00000000e+00]\n",
      " [9.09297427e-01 1.00000000e+00 2.00000000e+00 4.00000000e+00\n",
      "  8.00000000e+00 1.60000000e+01 3.20000000e+01]\n",
      " [1.41120008e-01 1.00000000e+00 3.00000000e+00 9.00000000e+00\n",
      "  2.70000000e+01 8.10000000e+01 2.43000000e+02]]\n",
      "(3, 7)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([   8.75909112,   15.        ,   32.        ,   78.        ,\n",
       "        206.        ,  570.        , 1622.        ])"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = np.array([])\n",
    "\n",
    "# Build out our matrix X \n",
    "for feature in x:\n",
    "    feature_vec = feature ** np.arange(k+1)\n",
    "    # print(feature_vec)\n",
    "    X = np.append(X, np.sin(feature))\n",
    "    X = np.append(X, feature_vec)\n",
    "\n",
    "X = X.reshape(3, k+2)\n",
    "print(X)\n",
    "print(X.shape)\n",
    "\n",
    "X.T @ y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# PS1: 3 Logistic Regression: Training Stability  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Text(0.5, 1.0, 'ds1_a.csv data')]"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import pandas as pd \n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "\n",
    "df_a = pd.read_csv(\"/Users/johnnydevriese/Documents/cs229-spring-22/XCS229-PS1/stability/ds1_a.csv\")\n",
    "df_b = pd.read_csv(\"/Users/johnnydevriese/Documents/cs229-spring-22/XCS229-PS1/stability/ds1_b.csv\")\n",
    "\n",
    "# print(df_a.head())\n",
    "# print(df_b.head())\n",
    "\n",
    "sns.scatterplot(data=df_a, x=\"x0\", y=\"x1\", hue=\"y\").set(title='ds1_a.csv data')\n",
    "# sns.scatterplot(data=df_b, x=\"x0\", y=\"x1\", hue=\"y\").set(title='ds1_b.csv data')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.,\n",
       "       2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.,\n",
       "       2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.,\n",
       "       2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.,\n",
       "       2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.,\n",
       "       2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.])"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "size = 3\n",
    "\n",
    "theta = np.zeros(size)\n",
    "# x = np.ones(size)\n",
    "# x.dot(theta)\n",
    "sigmoid = lambda x: 1 / 1 + np.exp(- x @ theta)\n",
    "\n",
    "sigmoid(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = np.array([[ 1.        , -0.3226045 ,  1.44016009],\n",
    "       [ 1.        ,  1.45213116,  2.26274285],\n",
    "       [ 1.        ,  0.85117646,  0.87461786],\n",
    "       [ 1.        , -0.42506633,  0.49448067],\n",
    "       [ 1.        ,  1.07977541,  4.15222455],\n",
    "       [ 1.        ,  0.06839514,  3.60693507],\n",
    "       [ 1.        ,  3.86229163, 25.99079097],\n",
    "       [ 1.        ,  0.63078087,  0.69715553],\n",
    "       [ 1.        , -0.64119999,  0.07896407],\n",
    "       [ 1.        ,  0.53135242,  4.50417546],\n",
    "       [ 1.        ,  2.19032426,  6.54381687],\n",
    "       [ 1.        , -0.38465533,  0.42296288],\n",
    "       [ 1.        ,  0.21679465,  5.01812571],\n",
    "       [ 1.        ,  0.4846679 ,  1.36387124],\n",
    "       [ 1.        ,  2.39608694, 10.87208984],\n",
    "       [ 1.        , -0.51197311,  0.86848666],\n",
    "       [ 1.        ,  0.61284557,  1.92105571],\n",
    "       [ 1.        ,  1.20247   ,  1.39818937],\n",
    "       [ 1.        ,  2.48716225,  4.41633191],\n",
    "       [ 1.        ,  0.27191322,  2.48805513],\n",
    "       [ 1.        ,  0.46650294,  3.4560205 ],\n",
    "       [ 1.        , -0.77155423,  0.70674626],\n",
    "       [ 1.        ,  0.74548073,  0.78677636],\n",
    "       [ 1.        ,  1.34588118,  1.84466679],\n",
    "       [ 1.        ,  0.03825659,  1.37679837],\n",
    "       [ 1.        ,  0.97144296,  2.33499786],\n",
    "       [ 1.        ,  0.73578508,  5.36219354],\n",
    "       [ 1.        , -0.98294485,  0.60613226],\n",
    "       [ 1.        , -1.06748414,  0.51752952],\n",
    "       [ 1.        ,  0.16444179,  1.19318199],\n",
    "       [ 1.        , -0.7898848 ,  1.0424866 ],\n",
    "       [ 1.        , -0.14329976,  0.56735751],\n",
    "       [ 1.        , -0.82024735,  0.49960062],\n",
    "       [ 1.        ,  0.66933574,  2.03132583],\n",
    "       [ 1.        ,  2.18580501,  4.79542536],\n",
    "       [ 1.        ,  1.24524603,  2.22477477],\n",
    "       [ 1.        , -0.38608243,  1.17125926],\n",
    "       [ 1.        ,  1.97265966,  0.94942542],\n",
    "       [ 1.        ,  0.11536834,  0.41934752],\n",
    "       [ 1.        , -0.62494875,  0.36937505],\n",
    "       [ 1.        ,  0.73560961,  2.00940088],\n",
    "       [ 1.        ,  1.79850535,  1.03246785],\n",
    "       [ 1.        , -0.14833684,  0.46835912],\n",
    "       [ 1.        , -0.09403357,  1.07422495],\n",
    "       [ 1.        ,  1.95126591, 11.27001531],\n",
    "       [ 1.        , -0.76667657,  0.48703998],\n",
    "       [ 1.        ,  0.53937355,  0.91782734],\n",
    "       [ 1.        , -0.22698133,  1.18536598],\n",
    "       [ 1.        , -0.39058305,  1.03621699],\n",
    "       [ 1.        ,  0.96225877,  1.0804548 ],\n",
    "       [ 1.        ,  2.87853267, 32.40471731],\n",
    "       [ 1.        ,  0.63533685,  1.31647006],\n",
    "       [ 1.        ,  2.44918624, 32.26914179],\n",
    "       [ 1.        ,  1.55800428,  1.41965492],\n",
    "       [ 1.        ,  1.58703176, 10.27789785],\n",
    "       [ 1.        ,  2.92302652,  6.32084127],\n",
    "       [ 1.        ,  1.16179168,  8.79339693],\n",
    "       [ 1.        ,  1.01926912,  7.27956453],\n",
    "       [ 1.        ,  1.64074981,  5.30590931],\n",
    "       [ 1.        ,  2.1625751 , 12.70579893],\n",
    "       [ 1.        ,  2.20355391,  6.93546526],\n",
    "       [ 1.        ,  1.80281512,  9.08987516],\n",
    "       [ 1.        ,  0.38185288,  2.08733116],\n",
    "       [ 1.        ,  2.73898669,  6.43298261],\n",
    "       [ 1.        ,  2.33229757, 13.46785592],\n",
    "       [ 1.        ,  2.1515753 ,  3.30175484],\n",
    "       [ 1.        ,  2.08755952,  7.46399068],\n",
    "       [ 1.        ,  2.42536537, 26.4483108 ],\n",
    "       [ 1.        ,  1.22952296,  2.63268864],\n",
    "       [ 1.        ,  2.29617283, 12.01655075],\n",
    "       [ 1.        ,  3.30064721, 11.28460368],\n",
    "       [ 1.        ,  0.98606951,  2.43854265],\n",
    "       [ 1.        ,  1.71111559,  4.78419937],\n",
    "       [ 1.        ,  1.43791364,  2.54852746],\n",
    "       [ 1.        ,  2.06546113,  6.82796588],\n",
    "       [ 1.        ,  2.6042525 , 18.17196626],\n",
    "       [ 1.        ,  2.56193154,  2.67573402],\n",
    "       [ 1.        ,  1.67306091,  2.28230367],\n",
    "       [ 1.        ,  3.07760672, 13.17400532],\n",
    "       [ 1.        ,  0.80343565,  1.95356398],\n",
    "       [ 1.        ,  0.29409223,  1.8304515 ],\n",
    "       [ 1.        ,  4.17743477, 28.43916382],\n",
    "       [ 1.        ,  2.20240356, 14.48263971],\n",
    "       [ 1.        ,  2.75638736,  9.03904178],\n",
    "       [ 1.        ,  1.59509206,  3.23851668],\n",
    "       [ 1.        ,  2.31360137,  8.12523688],\n",
    "       [ 1.        ,  2.25188961,  6.10723549],\n",
    "       [ 1.        ,  1.74848706,  4.97610269],\n",
    "       [ 1.        ,  1.94191761,  6.17617417],\n",
    "       [ 1.        ,  3.23970139, 36.2488673 ],\n",
    "       [ 1.        ,  0.77654359,  1.719952  ],\n",
    "       [ 1.        ,  1.53339444,  7.11126102],\n",
    "       [ 1.        ,  1.44950114,  7.08491125],\n",
    "       [ 1.        ,  1.62476639,  8.74420153],\n",
    "       [ 1.        ,  1.96366438,  8.17721712],\n",
    "       [ 1.        ,  1.79561844,  2.61247159],\n",
    "       [ 1.        ,  1.95348024,  1.6333998 ],\n",
    "       [ 1.        ,  1.86352418,  5.88989936],\n",
    "       [ 1.        ,  2.91729395, 22.77683958],\n",
    "       [ 1.        ,  1.31972857,  2.84750546]])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# PS3: Working on Poisson Regression and reshaping the gradient calcuation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n",
      "(3,)\n",
      "(2, 2)\n",
      "[[1 2]\n",
      " [3 4]]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([4, 6])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# our code looks so funky because the problem says we have to do\n",
    "#  **full batch gradient ascent**\n",
    "\n",
    "foo = np.array([1 ,2, 3,])  \n",
    "\n",
    "# just an array that is three long\n",
    "print(len(foo))\n",
    "print(foo.shape)\n",
    "\n",
    "# three by 1 matrix \n",
    "# three rows by 1 column \n",
    "foo.reshape(3, 1).shape\n",
    "\n",
    "bar = np.array([1, 2, 3, 4])\n",
    "\n",
    "bar_reshaped = bar.reshape(2, 2)\n",
    "\n",
    "print(bar_reshaped.shape)\n",
    "print(bar_reshaped)\n",
    "\n",
    "# np.sum(bar_reshaped, axis=0)\n",
    "\n",
    "# sum *down* the columns\n",
    "bar_reshaped.sum(axis=0)\n",
    "\n",
    "# np.exp(bar, out=(2,2))\n",
    "\n",
    "# print(foo)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-0.9262096826685897"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from numpy import linalg as LA\n",
    "\n",
    "LA.norm(np.array([1,2])) - LA.norm(np.array([1, 3]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "LA.norm(np.array([1,2]) - np.array([1,3]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "state = []\n",
    "\n",
    "for x in state:\n",
    "    # print(\"this is coef\", coef)\n",
    "    print(\"this is x\", x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# print(\"hello world\")\n",
    "\n",
    "\n",
    "def sign(a):\n",
    "    \"\"\"Gets the sign of a scalar input.\"\"\"\n",
    "    if a >= 0:\n",
    "        return 1\n",
    "    else:\n",
    "        return 0\n",
    "\n",
    "sign(22)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Fashion MNIST Problem scratchpad"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.00626879, 0.01704033, 0.04632042, 0.93037047],\n",
       "       [0.01203764, 0.08894682, 0.24178252, 0.65723302],\n",
       "       [0.00446236, 0.66227241, 0.24363641, 0.08962882]])"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "def softmax(x):\n",
    "    x = x - np.max(x,axis=1)[:,np.newaxis]\n",
    "    exp = np.exp(x)\n",
    "    s = exp / np.sum(exp,axis=1)[:,np.newaxis]\n",
    "    return s\n",
    "\n",
    "\n",
    "overflow_test = np.array([[10000, 10010, 10]])\n",
    "softmax([[22, 14, 16]])\n",
    "\n",
    "softmax(overflow_test)\n",
    "\n",
    "# correct solution:\n",
    "def softmax_from_stackoverflow(x):\n",
    "    \"\"\"Compute softmax values for each sets of scores in x.\"\"\"\n",
    "    e_x = np.exp(x - np.max(x))\n",
    "    return e_x / e_x.sum(axis=0) # only difference\n",
    "\n",
    "# def softmax_2(x):\n",
    "# my (correct) solution:\n",
    "def softmax_2(z):\n",
    "    assert len(z.shape) == 2\n",
    "    s = np.max(z, axis=1)\n",
    "    s = s[:, np.newaxis] # necessary step to do broadcasting\n",
    "    e_x = np.exp(z - s)\n",
    "    div = np.sum(e_x, axis=1)\n",
    "    div = div[:, np.newaxis] # dito\n",
    "    return e_x / div\n",
    "\n",
    "# BOOM -- this seems like it has the same result and just needs keepdims argument! \n",
    "def softmax_3(z):\n",
    "    return np.exp(z) / np.sum(np.exp(z), axis=1, keepdims=True)\n",
    "\n",
    "\n",
    "\n",
    "# softmax_from_stackoverflow(overflow_test)\n",
    "\n",
    "scores2D = np.array([[1, 2, 3, 6],\n",
    "                     [2, 4, 5, 6],\n",
    "                     [3, 8, 7, 6]])\n",
    "\n",
    "# softmax_from_stackoverflow(scores2D)\n",
    "softmax(scores2D)\n",
    "\n",
    "softmax_2(scores2D)\n",
    "\n",
    "softmax_3(scores2D)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0. 0.]]\n",
      "[0. 0.]\n"
     ]
    }
   ],
   "source": [
    "def foo():\n",
    "    return (\"foo\", \"bar\", \"baz\")\n",
    "\n",
    "foo, bar, baz = foo()\n",
    "\n",
    "# print(baz)\n",
    "\n",
    "input_size = 2\n",
    "num_hidden = 2\n",
    "num_output = 2\n",
    "\n",
    "\n",
    "W1 = np.random.normal(size = (input_size, num_hidden))\n",
    "b1 = np.zeros((1, num_hidden)) \n",
    "W2 = np.random.normal(size = (num_hidden, num_output)),  \n",
    "b2= np.zeros((1, num_output))\n",
    "dict(W1=W1, b1=b1, W2=W2, b2=b2)\n",
    "\n",
    "working = {\n",
    "        'W1': np.random.normal(size = (input_size, num_hidden)),\n",
    "        'b1': np.zeros(num_hidden),\n",
    "        'W2': np.random.normal(size = (num_hidden, 10)),\n",
    "        'b2': np.zeros(10)\n",
    "    }\n",
    "\n",
    "# print(working)\n",
    "\n",
    "b1 = np.zeros((1, 2))\n",
    "print(b1)\n",
    "\n",
    "b1_again = np.zeros(2)\n",
    "print(b1_again)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Naive Bayes Classifier "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'puttin': 1, 'fone': 2}"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ham = \"THANX 4 PUTTIN DA FONE DOWN ON ME!\"\n",
    "ham2 = \"So how are you really. What are you up to. How's the masters. And so on.\"\n",
    "\n",
    "ham_split = ham.lower().split()\n",
    "\n",
    "# would have to be a dict so we can lookup words \n",
    "ham_split\n",
    "word_count_dict = {}\n",
    "\n",
    "for word in ham_split:\n",
    "    # temp = dictionary.get(word, 0)\n",
    "    # dictionary[word] += 1\n",
    "\n",
    "    if word in word_count_dict:\n",
    "        word_count_dict[word] += 1\n",
    "    else:\n",
    "        word_count_dict[word] = 1\n",
    "    \n",
    "    # dictionary.setdefault(word, 1)\n",
    "\n",
    "# filter this dict if count > 5 \n",
    "# for key, value in dictionary.items():\n",
    "#     print(key)\n",
    "#     print(value)\n",
    "\n",
    "word_count_dict.items()\n",
    "\n",
    "word_count_dict[\"puttin\"] = 22\n",
    "word_count_dict[\"fone\"] = 12\n",
    "\n",
    "\n",
    "word_count_dict_filtered = dict(filter(lambda item: item[1] > 10, word_count_dict.items()))\n",
    "# foo = list(filter(lambda item: item[1] > 10, dictionary.items()))\n",
    "\n",
    "word_dict = {}\n",
    "idx = 0\n",
    "for key, _ in word_count_dict_filtered.items():\n",
    "    idx += 1\n",
    "    word_dict[key] = idx\n",
    "\n",
    "# dictionary\n",
    "word_dict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Filter dictionary: {8: 'u', 9: 'z', 10: 'j'}\n"
     ]
    }
   ],
   "source": [
    "my_dict = {8:'u',4:'t',9:'z',10:'j',5:'k',3:'s'}\n",
    "\n",
    "new_filt = dict(filter(lambda val: val[0] > 5, my_dict.items()))\n",
    "print(\"Filter dictionary:\",new_filt)\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "word_dict = {}\n",
    "for message in messages:\n",
    "    # word_list = get_words(message)\n",
    "    for word in word_list:\n",
    "        if word in word_dict:\n",
    "            word_dict[word] += 1\n",
    "        else:\n",
    "            word_dict[word] = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "N, V = len(messages), len(word_dictionary)\n",
    "data = np.zeros((N, V))\n",
    "for i, m in enumerate(messages):\n",
    "    for w in get_words(m):\n",
    "        if w in word_dictionary:\n",
    "            data[i, word_dictionary[w]] += 1\n",
    "return data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'word_count' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m/Users/johnnydevriese/projects/jupyter/cs229-scratchpad.ipynb Cell 22'\u001b[0m in \u001b[0;36m<cell line: 7>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      <a href='vscode-notebook-cell:/Users/johnnydevriese/projects/jupyter/cs229-scratchpad.ipynb#ch0000024?line=2'>3</a>\u001b[0m np\u001b[39m.\u001b[39mzeros((\u001b[39m1\u001b[39m, word_num))\n\u001b[1;32m      <a href='vscode-notebook-cell:/Users/johnnydevriese/projects/jupyter/cs229-scratchpad.ipynb#ch0000024?line=4'>5</a>\u001b[0m word_array \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39marray([])\u001b[39m.\u001b[39mreshape(\u001b[39m0\u001b[39m, word_num)\n\u001b[0;32m----> <a href='vscode-notebook-cell:/Users/johnnydevriese/projects/jupyter/cs229-scratchpad.ipynb#ch0000024?line=6'>7</a>\u001b[0m word_array \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39mvstack([word_array, word_count])\n",
      "\u001b[0;31mNameError\u001b[0m: name 'word_count' is not defined"
     ]
    }
   ],
   "source": [
    "word_num = 10\n",
    "\n",
    "np.zeros((1, word_num))\n",
    "\n",
    "word_array = np.array([]).reshape(0, word_num)\n",
    "\n",
    "word_array = np.vstack([word_array, word_count])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3]])"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ones((2, 3)).sum(axis=0)\n",
    "\n",
    "\n",
    "np.array([[1 ,2, 3], [4, 5, 6]]).sum(axis=0) # sums column wise. \n",
    "\n",
    "np.array([[1 ,2, 3], [4, 5, 6]]).sum(axis=1) # sums row wise. \n",
    "\n",
    "\n",
    "foo = np.array([[1 ,2, 3], [4, 5, 6]])\n",
    "\n",
    "foo[0:1,:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n",
       " [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n",
       " [0, 2, 4, 6, 8, 10, 12, 14, 16, 18],\n",
       " [0, 3, 6, 9, 12, 15, 18, 21, 24, 27],\n",
       " [0, 4, 8, 12, 16, 20, 24, 28, 32, 36],\n",
       " [0, 5, 10, 15, 20, 25, 30, 35, 40, 45],\n",
       " [0, 6, 12, 18, 24, 30, 36, 42, 48, 54],\n",
       " [0, 7, 14, 21, 28, 35, 42, 49, 56, 63],\n",
       " [0, 8, 16, 24, 32, 40, 48, 56, 64, 72],\n",
       " [0, 9, 18, 27, 36, 45, 54, 63, 72, 81]]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# [i for i in range(10) for j in range(10)] \n",
    "\n",
    "[[i*j for i in range(10)] for j in range(10)]\n",
    "# p_x_given_z(x[i], mu[j], sigma[j]) * phi[j] \n",
    "\n",
    "#     for i in range(n):\n",
    "#         for j in range(k):\n",
    "\n",
    "[[p_x_given_z(x[i], mu[j], sigma[j]) * phi[j] for i in range(n) for j in range(k)]]"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.10.5 ('pytorch-nightly')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.5"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "8a8bcccfb183d1298694efece6cf41240378bc61621e95c864629a40c5876542"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}