-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathvignette.html
More file actions
909 lines (879 loc) · 77.2 KB
/
Copy pathvignette.html
File metadata and controls
909 lines (879 loc) · 77.2 KB
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
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
<meta charset="utf-8">
<meta name="generator" content="quarto-1.2.335">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<meta name="author" content="Mindy Xu, Zoe Zhou, Amy Lyu, Jiashu Huang">
<meta name="dcterms.date" content="2023-12-13">
<title>Random Forest Vignette</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
ul.task-list li input[type="checkbox"] {
width: 0.8em;
margin: 0 0.8em 0.2em -1.6em;
vertical-align: middle;
}
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { color: #008000; } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { color: #008000; font-weight: bold; } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>
<script src="vignette_files/libs/clipboard/clipboard.min.js"></script>
<script src="vignette_files/libs/quarto-html/quarto.js"></script>
<script src="vignette_files/libs/quarto-html/popper.min.js"></script>
<script src="vignette_files/libs/quarto-html/tippy.umd.min.js"></script>
<script src="vignette_files/libs/quarto-html/anchor.min.js"></script>
<link href="vignette_files/libs/quarto-html/tippy.css" rel="stylesheet">
<link href="vignette_files/libs/quarto-html/quarto-syntax-highlighting.css" rel="stylesheet" id="quarto-text-highlighting-styles">
<script src="vignette_files/libs/bootstrap/bootstrap.min.js"></script>
<link href="vignette_files/libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
<link href="vignette_files/libs/bootstrap/bootstrap.min.css" rel="stylesheet" id="quarto-bootstrap" data-mode="light">
</head>
<body>
<div id="quarto-content" class="page-columns page-rows-contents page-layout-article">
<div id="quarto-margin-sidebar" class="sidebar margin-sidebar">
<nav id="TOC" role="doc-toc" class="toc-active">
<h2 id="toc-title">Table of contents</h2>
<ul>
<li><a href="#introduction" id="toc-introduction" class="nav-link active" data-scroll-target="#introduction">Introduction</a></li>
<li><a href="#example-data-hotel-reservation-data-to-implement" id="toc-example-data-hotel-reservation-data-to-implement" class="nav-link" data-scroll-target="#example-data-hotel-reservation-data-to-implement">Example Data – Hotel Reservation Data to Implement</a>
<ul class="collapse">
<li><a href="#data-description" id="toc-data-description" class="nav-link" data-scroll-target="#data-description">Data Description</a></li>
<li><a href="#load-packages-and-data" id="toc-load-packages-and-data" class="nav-link" data-scroll-target="#load-packages-and-data">Load Packages and Data</a></li>
<li><a href="#preprocess-the-data" id="toc-preprocess-the-data" class="nav-link" data-scroll-target="#preprocess-the-data">Preprocess the data</a></li>
<li><a href="#exploratory-data-analysis" id="toc-exploratory-data-analysis" class="nav-link" data-scroll-target="#exploratory-data-analysis">Exploratory Data Analysis</a></li>
<li><a href="#data-partition" id="toc-data-partition" class="nav-link" data-scroll-target="#data-partition">Data Partition</a></li>
</ul></li>
<li><a href="#preprocessing-recipe" id="toc-preprocessing-recipe" class="nav-link" data-scroll-target="#preprocessing-recipe">Preprocessing Recipe</a></li>
<li><a href="#cross-validation-setup" id="toc-cross-validation-setup" class="nav-link" data-scroll-target="#cross-validation-setup">Cross-Validation Setup</a></li>
<li><a href="#intuition-and-architecture" id="toc-intuition-and-architecture" class="nav-link" data-scroll-target="#intuition-and-architecture">Intuition and Architecture</a>
<ul class="collapse">
<li><a href="#understanding-decision-trees" id="toc-understanding-decision-trees" class="nav-link" data-scroll-target="#understanding-decision-trees">Understanding Decision Trees</a></li>
<li><a href="#random-forest-and-ensemble-models" id="toc-random-forest-and-ensemble-models" class="nav-link" data-scroll-target="#random-forest-and-ensemble-models">Random Forest and Ensemble models</a></li>
</ul></li>
<li><a href="#hyper-parameters-tuning" id="toc-hyper-parameters-tuning" class="nav-link" data-scroll-target="#hyper-parameters-tuning">Hyper-parameters Tuning</a></li>
<li><a href="#understanding-the-random-forest-model" id="toc-understanding-the-random-forest-model" class="nav-link" data-scroll-target="#understanding-the-random-forest-model">Understanding the Random Forest model</a>
<ul class="collapse">
<li><a href="#features-importance" id="toc-features-importance" class="nav-link" data-scroll-target="#features-importance">Features Importance</a></li>
</ul></li>
<li><a href="#final-thoughts" id="toc-final-thoughts" class="nav-link" data-scroll-target="#final-thoughts">Final Thoughts</a></li>
</ul>
</nav>
</div>
<main class="content" id="quarto-document-content">
<header id="title-block-header" class="quarto-title-block default">
<div class="quarto-title">
<h1 class="title">Random Forest Vignette</h1>
</div>
<div class="quarto-title-meta">
<div>
<div class="quarto-title-meta-heading">Author</div>
<div class="quarto-title-meta-contents">
<p>Mindy Xu, Zoe Zhou, Amy Lyu, Jiashu Huang </p>
</div>
</div>
<div>
<div class="quarto-title-meta-heading">Published</div>
<div class="quarto-title-meta-contents">
<p class="date">December 13, 2023</p>
</div>
</div>
</div>
</header>
<section id="introduction" class="level2">
<h2 class="anchored" data-anchor-id="introduction">Introduction</h2>
<blockquote class="blockquote">
<p>In this project, we are presenting a vignette on Random Forest. If you are new to this topic, then this vignette would be a great guideline for you to have a great understanding on Random forest model, and we will also show the sample code on a dataset to predict hotel cancellation using Random Forest.</p>
</blockquote>
<p><em>Learning Objectives:</em></p>
<ul>
<li><p>learn the intuitions behind Random Forest models</p>
<ul>
<li>Decision trees, hyper-parameters, and more</li>
</ul></li>
<li><p>Implement, tune, and evaluate Random Forest models in R</p></li>
</ul>
<p>Here we have a introductory video for you to better know what is Random Forest.</p>
<p><a href="https://www.youtube.com/watch?v=v6VJ2RO66Ag">Introductory Video</a></p>
</section>
<section id="example-data-hotel-reservation-data-to-implement" class="level2">
<h2 class="anchored" data-anchor-id="example-data-hotel-reservation-data-to-implement">Example Data – Hotel Reservation Data to Implement</h2>
<section id="data-description" class="level3">
<h3 class="anchored" data-anchor-id="data-description">Data Description</h3>
<p>This dataset is obtained from kaggle. There are 19 predictors in this data set. Booking status is the target varibale, indicating whether the reservation was canceled or not (binary: 2 values). There are 36275 observations in total. The goal of predicting hotel reservations is to forecast the number of bookings a hotel will receive for a specific date range, based on historical data and other relevant factors such as seasonality, market trends, and pricing strategies.</p>
<details>
<summary>
Data Dictionary
</summary>
<ul>
<li><p>Booking_ID: unique identifier of each booking</p></li>
<li><p>no_of_adults: Number of adults</p></li>
<li><p>no_of_children: Number of Children</p></li>
<li><p>no_of_weekend_nights: Number of weekend nights (Saturday or Sunday) the guest stayed or booked to stay at the hotel</p></li>
<li><p>no_of_week_nights: Number of week nights (Monday to Friday) the guest stayed or booked to stay at the hotel</p></li>
<li><p>type_of_meal_plan: Type of meal plan booked by the customer</p></li>
<li><p>required_car_parking_space: Does the customer require a car parking space? (0 - No, 1- Yes)</p></li>
<li><p>room_type_reserved: Type of room reserved by the customer. The values are ciphered (encoded) by INN Hotels.</p></li>
<li><p>lead_time: Number of days between the date of booking and the arrival date</p></li>
<li><p>arrival_year: Year of arrival date</p></li>
<li><p>arrival_month: Month of arrival date</p></li>
<li><p>arrival_date: Date of the month</p></li>
<li><p>market_segment_type: Market segment designation.</p></li>
<li><p>repeated_guest: Is the customer a repeated guest? (0 - No, 1- Yes)</p></li>
<li><p>no_of_previous_cancellations: Number of previous bookings that were canceled by the customer prior to the current booking</p></li>
<li><p>no_of_previous_bookings_not_canceled: Number of previous bookings not canceled by the customer prior to the current booking</p></li>
<li><p>avg_price_per_room: Average price per day of the reservation; prices of the rooms are dynamic. (in euros)</p></li>
<li><p>no_of_special_requests: Total number of special requests made by the customer (e.g. high floor, view from the room, etc)</p></li>
<li><p>booking_status: Flag indicating if the booking was canceled or not.</p></li>
</ul>
</details>
</section>
<section id="load-packages-and-data" class="level3">
<h3 class="anchored" data-anchor-id="load-packages-and-data">Load Packages and Data</h3>
<div class="cell">
<div class="sourceCode cell-code" id="cb1"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co"># load packages</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(tidyverse)</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(dplyr)</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(tidymodels)</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(janitor) <span class="do">## clean_names()</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(ranger) <span class="do">## random forest model engine</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(ggplot2)</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(corrplot)</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(ggbeeswarm)</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(patchwork)</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(vip)</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="co"># load data</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>hotel <span class="ot"><-</span> <span class="fu">read.csv</span>(<span class="st">"data/HotelReservations.csv"</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
</section>
<section id="preprocess-the-data" class="level3">
<h3 class="anchored" data-anchor-id="preprocess-the-data">Preprocess the data</h3>
<p>Before implementing the model, we need to make sure the dataset is ready for use. First, change variable names to a unified format. They will contain only “_”, numbers, and letters.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co"># cleaning predictor names</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>hotel <span class="ot"><-</span> <span class="fu">clean_names</span>(hotel)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Now let’s take a look at how our data is stored.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb3"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co"># view data structure and display the first 8 variables</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="fu">str</span>(hotel, <span class="at">vec.len =</span> <span class="dv">2</span>, <span class="at">list.len =</span> <span class="dv">8</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>'data.frame': 36275 obs. of 19 variables:
$ booking_id : chr "INN00001" "INN00002" ...
$ no_of_adults : int 2 2 1 2 2 ...
$ no_of_children : int 0 0 0 0 0 ...
$ no_of_weekend_nights : int 1 2 2 0 1 ...
$ no_of_week_nights : int 2 3 1 2 1 ...
$ type_of_meal_plan : chr "Meal Plan 1" "Not Selected" ...
$ required_car_parking_space : int 0 0 0 0 0 ...
$ room_type_reserved : chr "Room_Type 1" "Room_Type 1" ...
[list output truncated]</code></pre>
</div>
</div>
<p>Notice how the categorical variables are stored in character variables. We need to transform them into factors before we encode them into binary variables later.</p>
<div class="callout-important callout callout-style-default callout-captioned">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-caption-container flex-fill">
Action
</div>
</div>
<div class="callout-body-container callout-body">
<p>Use <code>lapply()</code> to turn categorical variables into factors.</p>
</div>
</div>
<div class="cell">
</div>
</section>
<section id="exploratory-data-analysis" class="level3">
<h3 class="anchored" data-anchor-id="exploratory-data-analysis">Exploratory Data Analysis</h3>
<p>After proper transformations, let’s explore our data a little before we move on to the models.</p>
<p>First, check the correlation between numerical variables.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb5"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>hotel <span class="sc">%>%</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a> <span class="fu">select</span>(is.numeric) <span class="sc">%>%</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">cor</span>() <span class="sc">%>%</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">corrplot</span>(<span class="at">type =</span> <span class="st">"lower"</span>, <span class="at">tl.cex =</span> <span class="fl">0.5</span>, <span class="at">tl.srt =</span> <span class="dv">45</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stderr">
<pre><code>Warning: Use of bare predicate functions was deprecated in tidyselect 1.1.0.
ℹ Please use wrap predicates in `where()` instead.
# Was:
data %>% select(is.numeric)
# Now:
data %>% select(where(is.numeric))</code></pre>
</div>
<div class="cell-output-display">
<p><img src="vignette_files/figure-html/unnamed-chunk-5-1.png" class="img-fluid" width="480"></p>
</div>
</div>
<p><code>no_of_repeated_guest</code> is positively correlated with <code>no_of_previous_bookings_not_canceled</code>. <code>Arrival year</code> is negatively correlated with <code>arrival_month</code>. Since most of the predictors do not overly correlate with each other, they likely store different information as well. Thus, we will use all of them as predictors for decision tree and random forest models to pool from later.</p>
<p>Next, make a histogram to see the distribution of the <code>booking status</code>.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb7"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>hotel <span class="sc">%>%</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a> <span class="fu">ggplot</span>(<span class="fu">aes</span>(<span class="at">x=</span>booking_status)) <span class="sc">+</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">geom_bar</span>() <span class="sc">+</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">labs</span>(<span class="at">title =</span> <span class="st">"Distribution of Booking Status"</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<p><img src="vignette_files/figure-html/unnamed-chunk-6-1.png" class="img-fluid" width="480"></p>
</div>
</div>
<p>From the plot, we can see that “Canceled” outnumbers “Not_Canceled” a lot. In order to deal with the imbalance, we may use stratified sampling during data partitioning and a <code>class_weight</code> parameter during the model fitting process. They will be illustrated in latter sections.</p>
<p>Lastly, let’s take a look at the correlation between our predictors and the target variable.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb8"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>numeric_vars <span class="ot"><-</span> <span class="fu">names</span>(hotel)[<span class="fu">sapply</span>(hotel, is.numeric)] <span class="co"># Get names of numeric variables</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>plots <span class="ot"><-</span> <span class="fu">list</span>() <span class="co"># List to store plots</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> (var <span class="cf">in</span> numeric_vars) {</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a> p <span class="ot"><-</span> <span class="fu">ggplot</span>(hotel, <span class="fu">aes_string</span>(<span class="at">x =</span> <span class="st">"booking_status"</span>, <span class="at">y =</span> var)) <span class="sc">+</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a> <span class="fu">geom_quasirandom</span>() <span class="sc">+</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a> <span class="fu">theme_minimal</span>() <span class="sc">+</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a> <span class="fu">ggtitle</span>(var) <span class="sc">+</span> </span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a> <span class="fu">scale_x_discrete</span>(<span class="at">labels =</span> <span class="fu">c</span>(<span class="st">"C"</span>, <span class="st">"NC"</span>)) <span class="sc">+</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a> <span class="fu">theme</span>(<span class="at">axis.title.y =</span> <span class="fu">element_text</span>(<span class="at">size =</span> <span class="fu">rel</span>(<span class="fl">0.6</span>)), <span class="at">axis.title.x =</span> <span class="fu">element_text</span>(<span class="at">size =</span> <span class="fu">rel</span>(<span class="fl">0.6</span>)), <span class="at">axis.text.y =</span> <span class="fu">element_text</span>(<span class="at">size =</span> <span class="fu">rel</span>(<span class="fl">0.6</span>)), <span class="at">axis.text.x =</span> <span class="fu">element_text</span>(<span class="at">size =</span> <span class="fu">rel</span>(<span class="fl">0.6</span>)), <span class="at">title =</span> <span class="fu">element_text</span>(<span class="at">size =</span> <span class="fu">rel</span>(<span class="fl">0.6</span>)), ) </span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a> plots[[var]] <span class="ot"><-</span> p <span class="co"># Store the plot in the list</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a> </span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>}</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stderr">
<pre><code>Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
ℹ Please use tidy evaluation idioms with `aes()`.
ℹ See also `vignette("ggplot2-in-packages")` for more information.</code></pre>
</div>
</div>
<div class="cell">
<div class="sourceCode cell-code" id="cb10"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>plots[[<span class="dv">1</span>]] <span class="sc">+</span> plots[[<span class="dv">2</span>]] <span class="sc">+</span> plots[[<span class="dv">3</span>]] <span class="sc">+</span> plots[[<span class="dv">4</span>]] <span class="sc">+</span> plots[[<span class="dv">5</span>]] <span class="sc">+</span> plots[[<span class="dv">6</span>]] <span class="sc">+</span> plots[[<span class="dv">7</span>]] <span class="sc">+</span> plots[[<span class="dv">8</span>]] <span class="sc">+</span> plots[[<span class="dv">9</span>]] <span class="sc">+</span> plots[[<span class="dv">10</span>]] <span class="sc">+</span> plots[[<span class="dv">11</span>]] <span class="sc">+</span> plots[[<span class="dv">12</span>]] <span class="sc">+</span> plots[[<span class="dv">13</span>]] <span class="sc">+</span> plots[[<span class="dv">14</span>]] </span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<p><img src="vignette_files/figure-html/unnamed-chunk-8-1.png" class="img-fluid" width="672"></p>
</div>
</div>
<p><code>lead_time</code> seems to be a strong predictor; <code>no_of_previous_booking_not_canceled</code> and <code>no_of_special_requests</code> also have a decent correlation with our target. We can later confirm these assumptions by inspecting feature importance in the random forest model.</p>
</section>
<section id="data-partition" class="level3">
<h3 class="anchored" data-anchor-id="data-partition">Data Partition</h3>
<p>Split the dataset into a training and a testing set. Use “booking_status” as the stratification variable to ensure it has equivalent proportions in two sets.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb11"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="fu">set.seed</span>(<span class="dv">3435</span>)</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>hotel_split <span class="ot"><-</span> <span class="fu">initial_split</span>(hotel, <span class="at">strata=</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a> <span class="st">"booking_status"</span>, <span class="at">prop =</span> <span class="fl">0.7</span>)</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>hotel_train <span class="ot"><-</span> <span class="fu">training</span>(hotel_split)</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>hotel_test <span class="ot"><-</span> <span class="fu">testing</span>(hotel_split)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<div class="callout-important callout callout-style-default callout-captioned">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-caption-container flex-fill">
Action
</div>
</div>
<div class="callout-body-container callout-body">
<p>Check the dimension of training data and testing data to see if the data has been split correctly.</p>
</div>
</div>
</section>
</section>
<section id="preprocessing-recipe" class="level2">
<h2 class="anchored" data-anchor-id="preprocessing-recipe">Preprocessing Recipe</h2>
<p>Now let’s create a recipe for our dataset.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb12"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Create a recipe for the dataset</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>hotel_recipe <span class="ot"><-</span> <span class="fu">recipe</span>(booking_status <span class="sc">~</span>., <span class="at">data =</span> hotel_train) </span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Limit the amount of factor levels for each predictor using <code>step_other()</code>. Factor levels with an occurring frequency less than 0.05 would be pooled to “other”.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb13"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>hotel_recipe <span class="ot"><-</span> hotel_recipe <span class="sc">%>%</span> </span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a> <span class="fu">step_other</span>(<span class="fu">all_nominal_predictors</span>(), <span class="at">threshold =</span> <span class="fl">0.05</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Using <code>step_dummy()</code>, encode factor variables to multiple binary variables which correspond to each factor level.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb14"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>hotel_recipe <span class="ot"><-</span> hotel_recipe <span class="sc">%>%</span> </span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a> <span class="fu">step_dummy</span>(<span class="fu">all_nominal_predictors</span>()) </span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
</section>
<section id="cross-validation-setup" class="level2">
<h2 class="anchored" data-anchor-id="cross-validation-setup">Cross-Validation Setup</h2>
<p>K-fold cross-validation is a statistical technique that helps assess a model’s ability to generalize. By <strong>partitioning</strong> the entire dataset in to <strong>k smaller sets</strong> and <strong>repeatedly train/evaluate</strong> the model on different sets, it ensures all data has a chance of appearing in the training and evaluation set. As a result, the assessment of the model would be much <strong>more robust</strong>, since it is almost impossible for a model that overfits to perform well in all folds.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb15"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="co"># 10-fold Cross validation</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>hotel_folds <span class="ot"><-</span> <span class="fu">vfold_cv</span>(hotel_train, <span class="at">v =</span> <span class="dv">10</span>, <span class="at">strata =</span> booking_status)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<div class="callout-important callout callout-style-default callout-captioned">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-caption-container flex-fill">
Action
</div>
</div>
<div class="callout-body-container callout-body">
<p>Try to change the folds number for the cross validation to see if the results change.</p>
</div>
</div>
</section>
<section id="intuition-and-architecture" class="level2">
<h2 class="anchored" data-anchor-id="intuition-and-architecture">Intuition and Architecture</h2>
<section id="understanding-decision-trees" class="level3">
<h3 class="anchored" data-anchor-id="understanding-decision-trees">Understanding Decision Trees</h3>
<p><strong>Decision Trees</strong> are a fundamental component of many machine learning algorithms, known for their simplicity and interpretability. Decision trees handle <strong>both categorical</strong> and <strong>numerical</strong> data and can model complex relationships with <strong>a series of simple decisions</strong>.</p>
<p>Imagine a decision tree as a tree-like model of decisions, resembling a flowchart, where each internal node represents a test on an attribute, each branch represents the outcome of the test, and each leaf node represents a class label (a decision taken after computing all attributes). The paths from root to leaf represent classification rules.</p>
<p>However, they are prone to <strong>overfitting</strong>, especially when they are overly deep and complex. A tree that perfectly models the training data can fail to generalize to new, unseen data. Thus, balancing the depth of the tree and the amount of training data is crucial for building an effective decision tree model.</p>
<hr>
<p>Now let’s implement a basic decision tree. <code>decision_tree()</code> defines a model as a set of if/then statements that creates a tree-based structure.</p>
<p>- <code>set_mode()</code> specifies the type of problem we are handling</p>
<p>- <code>set_engine()</code> specifies the type of package/system used to fit the model later.</p>
<p>- <code>set_args()</code> specifies the values of arguments of <code>decision_tree()</code>; here we set the depth of the tree to be in the range of [1, 15].</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb16"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Define the model (Decision Tree)</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>dt_model<span class="ot"><-</span><span class="fu">decision_tree</span>() <span class="sc">%>%</span> </span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">set_mode</span>(<span class="st">"classification"</span>) <span class="sc">%>%</span> <span class="do">## type of tasks</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">set_engine</span>(<span class="st">"rpart"</span>) <span class="sc">%>%</span> <span class="do">## type of engine used to fit the model</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a> <span class="fu">set_args</span>(<span class="fu">tree_depth</span>(<span class="fu">c</span>(1L, 15L))) <span class="do">## Other parameters</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Create a workflow object, set its recipe to hotel_recipe, and add dt_model as its model.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb17"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="co"># combine the model and the dataset to a workflow</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>dt_wf <span class="ot"><-</span> <span class="fu">workflow</span>() <span class="sc">%>%</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">add_recipe</span>(hotel_recipe) <span class="sc">%>%</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">add_model</span>(dt_model)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Use <code>fit_resamples()</code> to fit multiple models on the cross-validation folds we created earlier. - use “metrics =” to specify what to keep track for each model’s performance evaluation.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb18"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="co"># fit the model</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>hotel_results_dt <span class="ot"><-</span> <span class="fu">fit_resamples</span>(</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a> dt_wf,</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a> <span class="at">resamples =</span> hotel_folds, <span class="do">## cross-validation</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a> <span class="at">metrics =</span> <span class="fu">metric_set</span>(roc_auc, accuracy, sensitivity, specificity) <span class="do">## metrics to keep track on</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Let’s see how this model performed on the training set and testing set.</p>
<p>First, retrieve the training set metrics recorded during the training process. Check the variance of the metrics across different folds in order to look for signs of overfitting.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb19"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>results_summary_dt <span class="ot"><-</span> hotel_results_dt <span class="sc">%>%</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a> <span class="fu">collect_metrics</span>(<span class="at">summarize =</span> <span class="cn">FALSE</span>) <span class="sc">%>%</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">select</span>(<span class="fu">c</span>(<span class="st">".metric"</span>, <span class="st">".estimate"</span>)) <span class="sc">%>%</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">group_by</span>(.metric) <span class="sc">%>%</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a> <span class="fu">summarise</span>(<span class="at">variance =</span> <span class="fu">var</span>(.estimate))</span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>results_summary_dt</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code># A tibble: 4 × 2
.metric variance
<chr> <dbl>
1 accuracy 0.0000342
2 roc_auc 0.0000763
3 sensitivity 0.000212
4 specificity 0.0000242</code></pre>
</div>
</div>
<p>We see that the metrics does not vary too much across different folds. This means the model did not overfit. Let’s proceed to assess the model on the testing set.</p>
<p>Fit the model again, but this time on the entire training set.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb21"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>dt_fit_train <span class="ot"><-</span> <span class="fu">fit</span>(dt_wf, <span class="at">data =</span> hotel_train)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Augment the testing set using the fitted model.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb22"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>dt_test <span class="ot"><-</span> <span class="fu">augment</span>(dt_fit_train,</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a> hotel_test) <span class="sc">%>%</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">select</span>(booking_status, <span class="fu">starts_with</span>(<span class="st">".pred"</span>))</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>predictions <span class="ot"><-</span> dt_test <span class="sc">%>%</span></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a> <span class="fu">select</span>(booking_status, .pred_class, .pred_Canceled)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Calculate the four metrics and present them in a tibble.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb23"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a>sensitivity_val <span class="ot"><-</span> predictions <span class="sc">%>%</span> <span class="fu">sens</span>(<span class="at">truth =</span> booking_status, <span class="at">estimate =</span> .pred_class)</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>specificity_val <span class="ot"><-</span> predictions <span class="sc">%>%</span> <span class="fu">spec</span>(<span class="at">truth =</span> booking_status, <span class="at">estimate =</span> .pred_class)</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>accuracy_val <span class="ot"><-</span> predictions <span class="sc">%>%</span> <span class="fu">accuracy</span>(<span class="at">truth =</span> booking_status, <span class="at">estimate =</span> .pred_class)</span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>roc_auc_val <span class="ot"><-</span> predictions <span class="sc">%>%</span> <span class="fu">roc_auc</span>(<span class="at">truth =</span> booking_status, .pred_Canceled)</span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>model_metrics <span class="ot"><-</span> <span class="fu">tibble</span>(</span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a> <span class="at">.metric =</span> <span class="fu">c</span>(<span class="st">"accuracy"</span>, <span class="st">"roc_auc"</span>, <span class="st">"sensitivity"</span>, <span class="st">"specificity"</span>),</span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a> <span class="at">test =</span> <span class="fu">c</span>(accuracy_val<span class="sc">$</span>.estimate, roc_auc_val<span class="sc">$</span>.estimate, sensitivity_val<span class="sc">$</span>.estimate, specificity_val<span class="sc">$</span>.estimate)</span>
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a>)</span>
<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a>model_metrics</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code># A tibble: 4 × 2
.metric test
<chr> <dbl>
1 accuracy 0.824
2 roc_auc 0.826
3 sensitivity 0.688
4 specificity 0.891</code></pre>
</div>
</div>
<div class="callout-important callout callout-style-default callout-captioned">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-caption-container flex-fill">
Action
</div>
</div>
<div class="callout-body-container callout-body">
<p>Play around with different parameters - engine, tree_depth, number of folds, etc. - and see if you can achieve a higher performance.</p>
</div>
</div>
<hr>
</section>
<section id="random-forest-and-ensemble-models" class="level3">
<h3 class="anchored" data-anchor-id="random-forest-and-ensemble-models">Random Forest and Ensemble models</h3>
<p><img src="image/img-decisiontree.png" class="img-fluid"></p>
<p>The Random Forest algorithm is <strong>an ensemble learning method</strong>, primarily used for classification and regression. It constructs a multitude of decision trees at training time. The fundamental concept is simple: combine the predictions from multiple decision trees to produce a more accurate prediction than a single decision tree.</p>
<p>Each tree in a random forest is built from <strong>a sample drawn with replacement (bootstrap sample)</strong> from the training set. Furthermore, when splitting a node during the construction of the tree, the split is chosen from <strong>a random subset of the features</strong>, rather than the best split among all features. This strategy of ‘bagging’ and feature randomness introduces diversity among the trees, ultimately leading to a <strong>more robust</strong> overall prediction and <strong>reducing the risk of overfitting</strong>.</p>
<p>Additionally, random forests provide a measure of <strong>feature importance</strong>, which can be insightful for understanding the predictive power of individual features in the model; the algorithm can be <strong>parallelized</strong> for execution because each tree in the forest is built independently of the others, which makes the algorithm well-suited for modern multi-processor computers; it does <strong>not require feature scaling</strong> (like standardization or normalization) before input, as it does not rely on distance calculations.</p>
<hr>
<p>Use <code>rand_forest()</code> to implement a random forest model. Similar to the decision tree model we implemented earlier, use <code>set_mode()</code> and <code>set_engine()</code> to complete our model definition.</p>
<p>There is a couple of parameters you can play around with:</p>
<p>- <code>mtry</code>: the number of random sampled predictors used for each split</p>
<p>- <code>trees</code>: number of trees</p>
<p>- <code>min_n</code>: minimum number of data needed in a node to split further into two branches.</p>
<p>There are several ways to determine the best way to split when building a tree. the ranger engine allows us to specify it. We set <code>importance = impurity</code> in <code>set_engine()</code>, so that the engine used gini index to determine how to split.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb25"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>rf_model <span class="ot"><-</span> <span class="fu">rand_forest</span>(<span class="at">mtry =</span> <span class="dv">10</span>,</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a> <span class="at">trees =</span> <span class="dv">10</span>, </span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a> <span class="at">min_n =</span> <span class="dv">10</span>) <span class="sc">%>%</span> </span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">set_mode</span>(<span class="st">"classification"</span>) <span class="sc">%>%</span></span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a> <span class="fu">set_engine</span>(<span class="st">"ranger"</span>, <span class="at">importance =</span> <span class="st">"impurity"</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Again, combine the model and recipe into a workflow.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb26"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>rf_wf <span class="ot"><-</span> <span class="fu">workflow</span>() <span class="sc">%>%</span> </span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a> <span class="fu">add_model</span>(rf_model) <span class="sc">%>%</span> </span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">add_recipe</span>(hotel_recipe)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Fit the model using <code>fit_resamples()</code>. You will notice this time it takes longer for the model to fit.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb27"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="co"># fit the model</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>hotel_results_rf <span class="ot"><-</span> <span class="fu">fit_resamples</span>(</span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a> rf_wf,</span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a> <span class="at">resamples =</span> hotel_folds,</span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a> <span class="at">metrics =</span> <span class="fu">metric_set</span>(roc_auc, accuracy, sensitivity, specificity) <span class="do">## metrics to keep track on</span></span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Check the variance of the model metrics across different folds</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb28"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="co"># summarize the result</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>results_summary_rf <span class="ot"><-</span> hotel_results_rf <span class="sc">%>%</span></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">collect_metrics</span>(<span class="at">summarize =</span> <span class="cn">FALSE</span>) <span class="sc">%>%</span></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">select</span>(<span class="fu">c</span>(<span class="st">".metric"</span>, <span class="st">".estimate"</span>)) <span class="sc">%>%</span></span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a> <span class="fu">group_by</span>(.metric) <span class="sc">%>%</span></span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a> <span class="fu">summarise</span>(<span class="at">variance =</span> <span class="fu">var</span>(.estimate))</span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a>results_summary_rf</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code># A tibble: 4 × 2
.metric variance
<chr> <dbl>
1 accuracy 0.0000411
2 roc_auc 0.0000135
3 sensitivity 0.000153
4 specificity 0.0000409</code></pre>
</div>
</div>
<p>Again, we do not see clear signs of overfitting. Let’s proceed to perform the same evaluation we did on the decision tree model.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb30"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a>rf_fit_train <span class="ot"><-</span> <span class="fu">fit</span>(rf_wf, <span class="at">data =</span> hotel_train)</span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>rf_test <span class="ot"><-</span> <span class="fu">augment</span>(rf_fit_train,</span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a> hotel_test) <span class="sc">%>%</span></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">select</span>(booking_status, <span class="fu">starts_with</span>(<span class="st">".pred"</span>))</span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a>predictions <span class="ot"><-</span> rf_test <span class="sc">%>%</span></span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a> <span class="fu">select</span>(booking_status, .pred_class, .pred_Canceled)</span>
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-9"><a href="#cb30-9" aria-hidden="true" tabindex="-1"></a>sensitivity_val <span class="ot"><-</span> predictions <span class="sc">%>%</span> <span class="fu">sens</span>(<span class="at">truth =</span> booking_status, <span class="at">estimate =</span> .pred_class)</span>
<span id="cb30-10"><a href="#cb30-10" aria-hidden="true" tabindex="-1"></a>specificity_val <span class="ot"><-</span> predictions <span class="sc">%>%</span> <span class="fu">spec</span>(<span class="at">truth =</span> booking_status, <span class="at">estimate =</span> .pred_class)</span>
<span id="cb30-11"><a href="#cb30-11" aria-hidden="true" tabindex="-1"></a>accuracy_val <span class="ot"><-</span> predictions <span class="sc">%>%</span> <span class="fu">accuracy</span>(<span class="at">truth =</span> booking_status, <span class="at">estimate =</span> .pred_class)</span>
<span id="cb30-12"><a href="#cb30-12" aria-hidden="true" tabindex="-1"></a>roc_auc_val <span class="ot"><-</span> predictions <span class="sc">%>%</span> <span class="fu">roc_auc</span>(<span class="at">truth =</span> booking_status, .pred_Canceled)</span>
<span id="cb30-13"><a href="#cb30-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-14"><a href="#cb30-14" aria-hidden="true" tabindex="-1"></a>model_metrics <span class="ot"><-</span> <span class="fu">tibble</span>(</span>
<span id="cb30-15"><a href="#cb30-15" aria-hidden="true" tabindex="-1"></a> <span class="at">.metric =</span> <span class="fu">c</span>(<span class="st">"accuracy"</span>, <span class="st">"roc_auc"</span>, <span class="st">"sensitivity"</span>, <span class="st">"specificity"</span>),</span>
<span id="cb30-16"><a href="#cb30-16" aria-hidden="true" tabindex="-1"></a> <span class="at">test =</span> <span class="fu">c</span>(accuracy_val<span class="sc">$</span>.estimate, roc_auc_val<span class="sc">$</span>.estimate, sensitivity_val<span class="sc">$</span>.estimate, specificity_val<span class="sc">$</span>.estimate)</span>
<span id="cb30-17"><a href="#cb30-17" aria-hidden="true" tabindex="-1"></a>)</span>
<span id="cb30-18"><a href="#cb30-18" aria-hidden="true" tabindex="-1"></a>model_metrics</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code># A tibble: 4 × 2
.metric test
<chr> <dbl>
1 accuracy 0.891
2 roc_auc 0.948
3 sensitivity 0.799
4 specificity 0.936</code></pre>
</div>
</div>
<p>Notice a decent improvement in all four metrics compared to the decision tree model. It supports and demonstrates the idea that an ensemble model make predictions than a single model.</p>
<div class="callout-important callout callout-style-default callout-captioned">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-caption-container flex-fill">
Action
</div>
</div>
<div class="callout-body-container callout-body">
<p>Try altering the number of trees or the max depths of the trees to see if the results change. Can you achieve a better model performance?</p>
</div>
</div>
</section>
</section>
<section id="hyper-parameters-tuning" class="level2">
<h2 class="anchored" data-anchor-id="hyper-parameters-tuning">Hyper-parameters Tuning</h2>
<p>As you notice in the last section, a few adjustment in the model parameters may result in big difference in its final performance.</p>
<p>In a random forest model, there is a couple of important hyper-parameters to tune:</p>
<details>
<summary>
Overview of some common hyper-paremeters
</summary>
<p>Number of Variables per split (<code>mtry</code> in <code>rand_forest()</code>): This is the number of variables to possibly split at each node. Higher values more likely result in overfitting.</p>
<p>Number of Trees (<code>trees</code> in <code>rand_forest()</code>): This is the number of trees in the forest. Generally, more trees increase model performance and make the model more robust, but also increase computational cost.</p>
<p>Maximum Depth of Trees (<code>max_depth</code> in the <code>ranger</code> engine): This determines the maximum depth of each tree. Deeper trees can model more complex patterns, but they can also lead to overfitting. When there is a minimum number of samples required to split a node, you may set this to None.</p>
<p>Minimum Samples Split (<code>min_n</code> in <code>rand_forest()</code>): This is the minimum number of samples required to split an internal node. Higher values prevent creating nodes that might overfit to your data.</p>
<p>Criterion (<code>importance</code> in the <code>ranger</code> engine): The function to measure the quality of a split. Supported criteria are “impurity” for the Gini impurity and “none” for the information gain.</p>
<p>Class Weight (<code>class.weight</code> in the <code>ranger</code> engine): This parameter is used to balance the dataset. It’s especially important when dealing with imbalanced datasets</p>
</details>
<p>In this section we will learn how to use grid to search for the best parameter combination. For simplicity we only focus on three parameters: <code>mtry</code>, <code>trees</code>, and <code>min_n</code>.</p>
<p>First we need to create another model using <code>tune()</code> as placeholders for parameter values.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb32"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Define the model (Random Forest)</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>rf_model_tune <span class="ot"><-</span> <span class="fu">rand_forest</span>(<span class="at">mtry =</span> <span class="fu">tune</span>(), <span class="do">## number of random sampled predictors used for each split</span></span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a> <span class="at">trees =</span> <span class="fu">tune</span>(), <span class="do">## number of trees</span></span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a> <span class="at">min_n =</span> <span class="fu">tune</span>()) <span class="sc">%>%</span> <span class="do">## minimum number of data points needed in a node to split</span></span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a> <span class="fu">set_mode</span>(<span class="st">"classification"</span>) <span class="sc">%>%</span> <span class="do">## type of tasks</span></span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a> <span class="fu">set_engine</span>(<span class="st">"ranger"</span>, <span class="at">importance =</span> <span class="st">"impurity"</span>) <span class="do">## type of engine used to fit the model</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Next, create a grid that specifies the range of values each parameter may hold. <code>levels</code> indicates how many values from the range will be selected. The selected values would divide each range into equal intervals.</p>
<p>For example, a grid with three tuning parameters and three levels will have 3^3 combinations of parameter lists. 3^3 models will be fitted, each corresponding to a combination of parameters.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb33"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a>rf_grid <span class="ot"><-</span> <span class="fu">grid_regular</span>(</span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a> <span class="fu">mtry</span>(<span class="fu">c</span>(<span class="dv">5</span>, <span class="dv">16</span>)),</span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">trees</span>(<span class="fu">c</span>(<span class="dv">50</span>, <span class="dv">100</span>)),</span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">min_n</span>(<span class="fu">c</span>(<span class="dv">10</span>, <span class="dv">20</span>)),</span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a> <span class="at">levels =</span> <span class="dv">3</span></span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Create a workflow as usual, but use <code>tune_grid(..., grid = )</code> to fit the model this time.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb34"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="co"># combine the model and the dataset to a workflow</span></span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>rf_wf_tune <span class="ot"><-</span> <span class="fu">workflow</span>() <span class="sc">%>%</span> </span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">add_model</span>(rf_model_tune) <span class="sc">%>%</span> </span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">add_recipe</span>(hotel_recipe)</span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a>hotel_results_rf_tune <span class="ot"><-</span> <span class="fu">tune_grid</span>(</span>
<span id="cb34-7"><a href="#cb34-7" aria-hidden="true" tabindex="-1"></a> rf_wf_tune,</span>
<span id="cb34-8"><a href="#cb34-8" aria-hidden="true" tabindex="-1"></a> <span class="at">resamples =</span> hotel_folds,</span>
<span id="cb34-9"><a href="#cb34-9" aria-hidden="true" tabindex="-1"></a> <span class="at">grid =</span> rf_grid)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p><code>show_best()</code> will show the best models out of all 27 and their performance metrics.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb35"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="fu">show_best</span>(hotel_results_rf_tune, <span class="at">metric =</span> <span class="st">"roc_auc"</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code># A tibble: 5 × 9
mtry trees min_n .metric .estimator mean n std_err .config
<int> <int> <int> <chr> <chr> <dbl> <int> <dbl> <chr>
1 10 75 10 roc_auc binary 0.953 10 0.00124 Preprocessor1_Model05
2 10 100 10 roc_auc binary 0.953 10 0.00111 Preprocessor1_Model08
3 10 100 15 roc_auc binary 0.952 10 0.00114 Preprocessor1_Model17
4 10 75 15 roc_auc binary 0.952 10 0.00111 Preprocessor1_Model14
5 16 75 10 roc_auc binary 0.952 10 0.00111 Preprocessor1_Model06</code></pre>
</div>
</div>
<p>The <code>std_err</code> column shows us that there is no sign of overfitting.</p>
<p>Before we proceed to augment the testing set, first we need to select the best model out of all 27 models, and finalize the workflow with the best parameter list.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb37"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a>best_params <span class="ot"><-</span> <span class="fu">select_best</span>(hotel_results_rf_tune, <span class="at">metric =</span> <span class="st">"accuracy"</span>) </span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a>rf_final_workflow_train <span class="ot"><-</span> <span class="fu">finalize_workflow</span>(rf_wf_tune, best_params) </span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Now we can repeat the evaluation process</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb38"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a>rf_final_fit_train <span class="ot"><-</span> <span class="fu">fit</span>(rf_final_workflow_train, <span class="at">data =</span> hotel_train) </span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a>rf_final_test <span class="ot"><-</span> <span class="fu">augment</span>(rf_final_fit_train, hotel_test) <span class="sc">%>%</span> </span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">select</span>(booking_status, <span class="fu">starts_with</span>(<span class="st">".pred"</span>))</span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a>predictions <span class="ot"><-</span> rf_final_test <span class="sc">%>%</span> </span>
<span id="cb38-6"><a href="#cb38-6" aria-hidden="true" tabindex="-1"></a> <span class="fu">select</span>(booking_status, .pred_class, .pred_Canceled)</span>
<span id="cb38-7"><a href="#cb38-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-8"><a href="#cb38-8" aria-hidden="true" tabindex="-1"></a>sensitivity_val <span class="ot"><-</span> predictions <span class="sc">%>%</span> <span class="fu">sens</span>(<span class="at">truth =</span> booking_status, <span class="at">estimate =</span> .pred_class) </span>
<span id="cb38-9"><a href="#cb38-9" aria-hidden="true" tabindex="-1"></a>specificity_val <span class="ot"><-</span> predictions <span class="sc">%>%</span> <span class="fu">spec</span>(<span class="at">truth =</span> booking_status, <span class="at">estimate =</span> .pred_class)</span>
<span id="cb38-10"><a href="#cb38-10" aria-hidden="true" tabindex="-1"></a>accuracy_val <span class="ot"><-</span> predictions <span class="sc">%>%</span> <span class="fu">accuracy</span>(<span class="at">truth =</span> booking_status, <span class="at">estimate =</span> .pred_class)</span>
<span id="cb38-11"><a href="#cb38-11" aria-hidden="true" tabindex="-1"></a>roc_auc_val <span class="ot"><-</span> predictions <span class="sc">%>%</span> <span class="fu">roc_auc</span>(<span class="at">truth =</span> booking_status, .pred_Canceled)</span>
<span id="cb38-12"><a href="#cb38-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-13"><a href="#cb38-13" aria-hidden="true" tabindex="-1"></a><span class="co"># Create a new variable to store the metrics</span></span>
<span id="cb38-14"><a href="#cb38-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-15"><a href="#cb38-15" aria-hidden="true" tabindex="-1"></a>model_metrics <span class="ot"><-</span> <span class="fu">tibble</span>(</span>
<span id="cb38-16"><a href="#cb38-16" aria-hidden="true" tabindex="-1"></a> <span class="at">.metric =</span> <span class="fu">c</span>(<span class="st">"accuracy"</span>, <span class="st">"roc_auc"</span>, <span class="st">"sensitivity"</span>, <span class="st">"specificity"</span>),</span>
<span id="cb38-17"><a href="#cb38-17" aria-hidden="true" tabindex="-1"></a> <span class="at">test =</span> <span class="fu">c</span>(accuracy_val<span class="sc">$</span>.estimate, roc_auc_val<span class="sc">$</span>.estimate, sensitivity_val<span class="sc">$</span>.estimate, specificity_val<span class="sc">$</span>.estimate)</span>
<span id="cb38-18"><a href="#cb38-18" aria-hidden="true" tabindex="-1"></a>)</span>
<span id="cb38-19"><a href="#cb38-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-20"><a href="#cb38-20" aria-hidden="true" tabindex="-1"></a>model_metrics</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code># A tibble: 4 × 2
.metric test
<chr> <dbl>
1 accuracy 0.899
2 roc_auc 0.954
3 sensitivity 0.811
4 specificity 0.943</code></pre>
</div>
</div>
<div class="callout-important callout callout-style-default callout-captioned">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-caption-container flex-fill">
Action
</div>
</div>
<div class="callout-body-container callout-body">
<p>Try to tune other parameters of the Random Forest model using a grid to see if the results change. Is there a better model performance?</p>
</div>
</div>
</section>
<section id="understanding-the-random-forest-model" class="level2">
<h2 class="anchored" data-anchor-id="understanding-the-random-forest-model">Understanding the Random Forest model</h2>
<section id="features-importance" class="level3">
<h3 class="anchored" data-anchor-id="features-importance">Features Importance</h3>
<p>Random Forest can be used to rank the importance of variables in a regression or classification problem.</p>
<p>Higher the value of mean decrease accuracy or mean decrease gini score , higher the importance of the variable in the model.</p>
<p>A good tool to visualize features importance is to use the VIP plot (Variable Importance Plot), you may use <code>vip()</code> function from the <code>vip</code> package as shown below:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb40"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a>rf_final_fit_train <span class="sc">%>%</span> <span class="fu">extract_fit_parsnip</span>() <span class="sc">%>%</span> </span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a> <span class="fu">vip</span>() <span class="sc">+</span></span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">theme_minimal</span>()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<p><img src="vignette_files/figure-html/unnamed-chunk-32-1.png" class="img-fluid" width="672"></p>
</div>
</div>
<p>As we analyzed before, leading_time is the most important feature after we plot the Variance Important Plot. So our results justified our preliminary exploratory analysis.</p>
</section>
</section>
<section id="final-thoughts" class="level2">
<h2 class="anchored" data-anchor-id="final-thoughts">Final Thoughts</h2>
<p>After reading this vignette, you should know how Random Forest work as a machine learning algorithm and how to implement this model in R through our step-by-step instruction. You should also know how to fine tune Random Forest by adjusting mtry, trees, min_n.</p>
<div class="callout-important callout callout-style-default callout-captioned">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-caption-container flex-fill">
Discussion
</div>
</div>
<div class="callout-body-container callout-body">
<p>Can you try fit Random Forest to some other datasets? How does it perform with Regression? Can you encapsulate fitting Random Forest model in R in a few steps?</p>
</div>
</div>
<p>Expecting to learn more? <em>Here are some excellent articles that may help you progress more in this topic:</em></p>
<p><a href="https://www.analyticsvidhya.com/blog/2021/06/understanding-random-forest/">Understand random forest algorithms with examples</a><a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<p><a href="https://www.hackerearth.com/practice/machine-learning/machine-learning-algorithms/tutorial-random-forest-parameter-tuning-r/tutorial/">Practical Tutorial on Random Forest and Parameter Tuning in R</a><a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></p>
</section>
<div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>
<ol>
<li id="fn1"><p>Sruthi E R (2023, October 26). *Understand random forest algorithms with examples (updated 2023)*. Analytics Vidhya. <https://www.analyticsvidhya.com/blog/2021/06/understanding-random-forest/><a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2"><p>Manish Saraswat (2023). *Practical Tutorial on Random Forest and Parameter Tuning in R* . R <https://www.hackerearth.com/practice/machine-learning/machine-learning-algorithms/tutorial-random-forest-parameter-tuning-r/tutorial/><a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section></div></main>
<!-- /main column -->
<script id="quarto-html-after-body" type="application/javascript">
window.document.addEventListener("DOMContentLoaded", function (event) {
const toggleBodyColorMode = (bsSheetEl) => {
const mode = bsSheetEl.getAttribute("data-mode");
const bodyEl = window.document.querySelector("body");
if (mode === "dark") {
bodyEl.classList.add("quarto-dark");
bodyEl.classList.remove("quarto-light");
} else {
bodyEl.classList.add("quarto-light");
bodyEl.classList.remove("quarto-dark");
}
}
const toggleBodyColorPrimary = () => {
const bsSheetEl = window.document.querySelector("link#quarto-bootstrap");
if (bsSheetEl) {
toggleBodyColorMode(bsSheetEl);
}
}
toggleBodyColorPrimary();
const icon = "";
const anchorJS = new window.AnchorJS();
anchorJS.options = {
placement: 'right',
icon: icon
};
anchorJS.add('.anchored');
const clipboard = new window.ClipboardJS('.code-copy-button', {
target: function(trigger) {
return trigger.previousElementSibling;
}
});
clipboard.on('success', function(e) {
// button target
const button = e.trigger;
// don't keep focus
button.blur();
// flash "checked"
button.classList.add('code-copy-button-checked');
var currentTitle = button.getAttribute("title");
button.setAttribute("title", "Copied!");
let tooltip;
if (window.bootstrap) {
button.setAttribute("data-bs-toggle", "tooltip");
button.setAttribute("data-bs-placement", "left");
button.setAttribute("data-bs-title", "Copied!");
tooltip = new bootstrap.Tooltip(button,
{ trigger: "manual",
customClass: "code-copy-button-tooltip",
offset: [0, -8]});
tooltip.show();
}
setTimeout(function() {
if (tooltip) {
tooltip.hide();
button.removeAttribute("data-bs-title");
button.removeAttribute("data-bs-toggle");
button.removeAttribute("data-bs-placement");
}
button.setAttribute("title", currentTitle);
button.classList.remove('code-copy-button-checked');
}, 1000);
// clear code selection
e.clearSelection();
});
function tippyHover(el, contentFn) {
const config = {
allowHTML: true,
content: contentFn,
maxWidth: 500,
delay: 100,
arrow: false,
appendTo: function(el) {
return el.parentElement;
},
interactive: true,
interactiveBorder: 10,
theme: 'quarto',
placement: 'bottom-start'
};
window.tippy(el, config);
}
const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]');
for (var i=0; i<noterefs.length; i++) {
const ref = noterefs[i];
tippyHover(ref, function() {
// use id or data attribute instead here
let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href');
try { href = new URL(href).hash; } catch {}
const id = href.replace(/^#\/?/, "");
const note = window.document.getElementById(id);
return note.innerHTML;
});
}
const findCites = (el) => {
const parentEl = el.parentElement;
if (parentEl) {
const cites = parentEl.dataset.cites;
if (cites) {
return {
el,
cites: cites.split(' ')
};
} else {
return findCites(el.parentElement)
}
} else {
return undefined;
}
};
var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]');
for (var i=0; i<bibliorefs.length; i++) {
const ref = bibliorefs[i];
const citeInfo = findCites(ref);
if (citeInfo) {
tippyHover(citeInfo.el, function() {
var popup = window.document.createElement('div');
citeInfo.cites.forEach(function(cite) {
var citeDiv = window.document.createElement('div');
citeDiv.classList.add('hanging-indent');
citeDiv.classList.add('csl-entry');
var biblioDiv = window.document.getElementById('ref-' + cite);
if (biblioDiv) {
citeDiv.innerHTML = biblioDiv.innerHTML;
}
popup.appendChild(citeDiv);
});
return popup.innerHTML;
});
}
}
});
</script>
</div> <!-- /content -->
</body></html>