My question seems a little vague so I will provide background context and my reproducible code to try and clarify.
I am interested in classifying crime occurrences in various neighbourhoods of a city, based on each neighbourhood's socioeconomic indicators. My end goal is to be able to generate a reasonably accurate prediction which would suggest the most likely neighbourhood that the next crime should occur. I chose to fit a multinomial regression model, and I am having a hard time interpreting its results.
Here is how my data looks:
> str(df)
'data.frame': 1796 obs. of 12 variables:
$ Time : chr "14:37:00" "14:37:00" "16:23:00" "00:10:00" ...
$ Neighbourhood : chr "Grand Boulevard" "Grand Boulevard" "West Town" "West Englewood" ...
$ Population : num 22209 22209 84698 26346 24976 ...
$ Area : num 1.74 1.74 4.58 3.15 2.55 2.95 3.15 1.04 7.15 1.28 ...
$ Density : chr "12,763.79" "12,763.79" "18,493.01" "8,363.81" ...
$ Crowded.Housing: num 3.3 3.3 2.3 4.8 2.7 3.3 4.8 2.4 6.3 9.4 ...
$ Poverty : num 29.3 29.3 14.7 34.4 8.9 27.8 34.4 21.7 28.6 41.7 ...
$ Unemployment : num 24.3 24.3 6.6 35.9 9.5 24 35.9 15.7 22.6 25.8 ...
$ Education : num 15.9 15.9 12.9 26.3 18.8 14.5 26.3 11.3 24.4 24.5 ...
$ Age : num 39.5 39.5 21.7 40.7 37.6 40.3 40.7 35.4 37.9 43.6 ...
$ Income : num 23472 23472 43198 11317 25113 ...
$ Hardship : num 57 57 10 89 29 60 89 26 73 92 ...
Here is the code for my model:
c.nnet = nnet::multinom(Neighbourhood ~
Crowded.Housing +
Poverty +
Unemployment +
Education +
Income +
Hardship,
data = df,
MaxNWts = 100000)
Here are some classification accuracy metrics:
> odds <- c.nnet[["fitted.values"]]
> pd = predict(c.nnet,type="class")
> table = table(df$Neighbourhood, pd); classAgreement(table)
$diag
[1] 0.6631403
$kappa
[1] 0.6451884
$rand
[1] 0.9560459
$crand
[1] 0.6035169
> sum(diag(table))/sum(table)
[1] 0.6631403
Lastly, here is the output of the predicted classes and the associated class probabilities.
>head(pd)
[1] Chatham Chatham West Town West Englewood New City Chatham
72 Levels: Albany Park Archer Heights Armour Square Ashburn Auburn Gresham Austin Avalon Park Avondale Belmont Cragin Bridgeport Brighton Park ... Woodlaw
> head(odds)
Albany Park Archer Heights Armour Square Ashburn Auburn Gresham Austin Avalon Park Avondale Belmont Cragin Bridgeport Brighton Park
1 8.293444e-04 3.078169e-04 3.394213e-04 5.070003e-04 0.0333699087 8.205015e-03 0.0140058699 3.519157e-04 0.0005199967 3.962345e-04 1.796575e-05
2 8.293444e-04 3.078169e-04 3.394213e-04 5.070003e-04 0.0333699087 8.205015e-03 0.0140058699 3.519157e-04 0.0005199967 3.962345e-04 1.796575e-05
3 7.276802e-04 2.796196e-06 1.540627e-03 9.642981e-03 0.0001623333 4.575838e-05 0.0004173684 1.229428e-03 0.0007718075 2.308536e-02 9.021844e-03
4 7.168266e-05 7.869570e-04 1.743114e-05 3.519012e-05 0.0473000895 9.256728e-02 0.0058524740 4.373425e-05 0.0002943829 4.752441e-06 6.214005e-07
5 2.376865e-03 3.647976e-04 3.261888e-03 5.958128e-02 0.0090540446 4.103546e-02 0.0028125946 9.329274e-03 0.0339153709 1.394973e-02 9.034131e-02
6 7.735586e-04 5.958576e-04 2.345032e-04 4.058962e-04 0.0833015893 2.374063e-02 0.0169124221 3.038695e-04 0.0005576943 2.163316e-04 1.263609e-05
As far as my understanding goes, the latter output (odds) represents the probability of each crime occurence belonging to each of the 72 unique neighbourhoods I have in my data, while the former (pd) represents the predicted classes based on my data set. This leads to my specific question; How can I use these predicted classes in order to generate some sort of forecast as to where the next crime is likely to occur (i.e. something like a time-series forecast with 1 step ahead)?
You can create a newdata
data frame with the values you want to predict over and then use the predict
function to obtain predicted probabilities for each class. For example,
# estimate model
library(nnet)
dat <- mtcars
dat$gear <- factor(dat$gear)
mod <- multinom(gear ~ mpg + hp, data = dat)
# what values we want predictions for
out_of_sample_data <- data.frame(mpg = c(19, 20), hp = c(130, 140))
# generate predicted probabilities
predict(mod, newdata = out_of_sample_data, type = "probs")
#> 3 4 5
#> 1 0.6993027 0.2777716 0.02292562
#> 2 0.6217686 0.2750779 0.10315351
Obviously, you'll need to populate your out of sample data with values you believe with occur in the future, which can be tricky (to say the least).