First RevealJs Deck!

Corey Cassell

3/6/23

About Me

  • My name is Corey Cassell, I am an engineer in the commercial aerospace industry and an aspiring data scientist.
  • I am currently closing out the final half of my data science masters program.
  • In particular I am interested in applying machine learning models to manufacturing problems to help predict and respond to daily production gaps before they occur.
## Here’s a classification project example that I completed for school - I will be using the caret library in conjunction with the wine dataset to do this analysis - The data I am using contains wines from different regions with price, rating, and description information. - The target variable is the wine province of origin. - Lets take a look at the dataset!

Sources and Data

Text Parsing

  • The following function was used to take in a dataset with a text field, remove any stop words, only include words that occured over a certain threshold, and determine sensitivity to word roots. ::: {.cell}
Code
wine_words <- function(df, j = 1000, stem=F){ 
  library(tidytext)
  library(SnowballC)
  data(stop_words)

  words <- df %>%
    unnest_tokens(word, description) %>%
    anti_join(stop_words) %>% # get rid of stop words
    filter(!(word %in% c("wine","pinot","vineyard")))
  
  if(stem){
    words <- words %>% 
      mutate(word = wordStem(word))
  }
  
  words <- words %>% 
    count(id, word) %>% 
    group_by(id) %>% 
    mutate(exists = (n>0)) %>% 
    ungroup %>% 
    group_by(word) %>% 
    mutate(total = sum(n)) %>% 
    filter(total > j) %>% 
    pivot_wider(id_cols = id, names_from = word, values_from = exists, values_fill = list(exists=0)) %>% 
    right_join(dplyr::select(df,id,province)) %>% 
    dplyr::select(-id) %>% 
    mutate(across(-province, ~replace_na(.x, F)))
}

:::

Feature Engineering

  • In this step I apply the previously discussed function and set my word thrshold at 1000 occurences.
  • Exploring the data I observed that of the 6 provinces I was attempting to predict, 4 were extremely under represented.
  • To address this I chose to resample and even out the lower represented provinces while undersampling the higher representation provinces. ::: {.cell}
Code
set.seed(500)
wine = read_rds("https://raw.githubusercontent.com/bobbyjy/MyData/main/pinot.rds")
#training the fit on the adjusted data set, played with some weightings but this didn't help a lot
wine <- wine %>% 
  mutate(points = scale(points, center = T, scale = T)) %>%
  mutate(price = scale(log(price), center = T, scale = T)) 

wino <- wine_words(wine, j=1000, stem = T)
wino$price <- wine$price
wino$points <- wine$points
wine_index <- createDataPartition(wino$province, p = 0.80, list = FALSE)
train <- wino[ wine_index, ]
###the model can't look at the test set...###
test <- wino[-wine_index, ]

####conduct data duplication on only the train set####
sample_size = 400

burg_sample <- train %>%
  filter(province=='Burgundy') %>% 
    sample_n(sample_size, replace = T)

cali_sample <- train %>%
  filter(province=='California') %>% 
    sample_n(800, replace = T) #800 got .84

casa_sample <- train %>%
  filter(province=='Casablanca_Valley') %>% 
    sample_n(sample_size, replace = T)

marl_sample <- train %>%
  filter(province=='Marlborough') %>% 
    sample_n(sample_size, replace = T)

york_sample <- train %>%
  filter(province=='New_York') %>% 
    sample_n(sample_size, replace = T)

oreg_sample <- train %>%
  filter(province=='Oregon') %>% 
    sample_n(800, replace = T) #800 got .84

train <- rbind(burg_sample,cali_sample,casa_sample,marl_sample,york_sample,oreg_sample)

#train

weight_train <- train %>% 
  mutate(weights=case_when(
    province=="Burgundy" ~ 1,
    province=="California" ~ 1,
    province=="Casablanca_Valley" ~ 1,
    province=="Marlborough" ~ 1,
    province=="New_York" ~ 1,
    province=="Oregon" ~ 1))

ctrl <- trainControl(method = "repeatedcv", number = 5, repeats = 1)

fit <- train(province ~ .,
             data = train,
             method = "rf",
             trControl = ctrl,
             ntree=100,
             weights = weight_train$weights
             )

 pred <- predict(fit, newdata=test)

:::

Results

  • To understand the overall validity of my model I used Kappa (the measure of how likely it would be to achieve these results at random) and a confusion matrix to visualize the quantity of correct and incorrect predictions by category. ::: {.cell}
Code
 confusionMatrix(factor(pred),factor(test$province))
Confusion Matrix and Statistics

                   Reference
Prediction          Burgundy California Casablanca_Valley Marlborough New_York
  Burgundy               198         15                 0           3        1
  California              11        613                 5           5        9
  Casablanca_Valley        0         12                21           3        1
  Marlborough              1         23                 0          24        1
  New_York                 1         21                 0           0       10
  Oregon                  27        107                 0          10        4
                   Reference
Prediction          Oregon
  Burgundy              24
  California            90
  Casablanca_Valley     14
  Marlborough           25
  New_York              10
  Oregon               384

Overall Statistics
                                          
               Accuracy : 0.7472          
                 95% CI : (0.7256, 0.7678)
    No Information Rate : 0.4728          
    P-Value [Acc > NIR] : < 2.2e-16       
                                          
                  Kappa : 0.6206          
                                          
 Mcnemar's Test P-Value : NA              

Statistics by Class:

                     Class: Burgundy Class: California Class: Casablanca_Valley
Sensitivity                   0.8319            0.7750                  0.80769
Specificity                   0.9700            0.8639                  0.98179
Pos Pred Value                0.8216            0.8363                  0.41176
Neg Pred Value                0.9721            0.8106                  0.99692
Prevalence                    0.1423            0.4728                  0.01554
Detection Rate                0.1184            0.3664                  0.01255
Detection Prevalence          0.1441            0.4381                  0.03048
Balanced Accuracy             0.9010            0.8195                  0.89474
                     Class: Marlborough Class: New_York Class: Oregon
Sensitivity                     0.53333        0.384615        0.7020
Specificity                     0.96929        0.980571        0.8686
Pos Pred Value                  0.32432        0.238095        0.7218
Neg Pred Value                  0.98687        0.990190        0.8571
Prevalence                      0.02690        0.015541        0.3270
Detection Rate                  0.01435        0.005977        0.2295
Detection Prevalence            0.04423        0.025105        0.3180
Balanced Accuracy               0.75131        0.682593        0.7853

:::