Modelling Efficient Military Deployments with Machine Learning — K-Means Clustering in R
By: Aj Gabriel
Tags: Machine Learning, Statistics, Data Science, Unsupervised Learning, R Programming

(If using a smart-phone this article is best viewed in landscape mode)

Armed forces in Latin America & the Caribbean are faced with the challenge of having to operate with a multi-dimensional mandate. In times of heightened civil unrest they are required to undertake peace-keeping operations, gang warfare driven by the arms-for-drugs trade calls for counter-insurgence style deployments and seasonal natural disasters often require their services to support the essential services under extreme conditions. With limited resources, every opportunity to prevent the unnecessary expenditure while maintaining effectiveness needs to be taken.

In this post I will demonstrate how the application of the K-means clustering algorithm, in the context of how Naval Forces in Latin America and the Caribbean, can be used to schedule efficient Naval deployments and reduce the number of unnecessary operations.

Preparing The Data

For this example I simulated 200 data points that represent the location of incidents that would result in the need for Naval resources to be deployed in the Caribbean Sea. The data have a timestamp that indicates the time of day of each incident on a 24-hour clock cycle. The specific area of focus is approximately 7,500 square miles, enclosed between:

latitudes — N18*00' and N17*20’

longitudes — W78*20' and W76*00'

(The Caribbean Sea in the vicinity of the south coast of Jamaica)

Our task is to identify any locations and times that tend to have a higher concentration of incidents and if so, allocate more military resources to those areas while reducing deployments to locations that rarely have incidents.

#You will require these packages to execute the code in this example

#effectively.

library("plotly", lib.loc="~/R/win-library/3.6")

library("dplyr", lib.loc="~/R/win-library/3.6")

library("ggplot2", lib.loc="~/R/win-library/3.6")

Now to simulate the data points.

#Generate data for example

set.seed(11)

LatCL1 <- round(rnorm(20, mean = 17.9, sd = 0.1), 2) set.seed(12)

LonCL1 <- round(rnorm(20, mean = -78.37, sd = 0.2), 2)

CL1 <- data.frame(LonCL1, LatCL1)

names(CL1) <- c('Longitude', 'Latitude') set.seed(21)

LatCL2 <- round(rnorm(50, mean = 17.73, sd = 0.033), 2) set.seed(22)

LonCL2 <- round(rnorm(50, mean = -78, sd = 0.25), 2)

CL2 <- data.frame(LonCL2, LatCL2)

names(CL2) <- c('Longitude', 'Latitude') set.seed(31)

LatCL3 <- round(rnorm(130, mean = 17.64, sd = 0.075), 2) set.seed(32)

LonCL3 <- round(rnorm(130, mean = -76.64, sd = 0.3), 2)

CL3 <- data.frame(LonCL3, LatCL3)

names(CL3) <- c('Longitude', 'Latitude')CL <- rbind(CL1, CL2, CL3)

We have generated 200 data points which represent the location of recorded incidents such as distress calls, reports of pirate-ship sightings (yes, there really are Pirates in the Caribbean), sailors lost-at-sea (requests for search and rescue services), interception of drugs/arms smugglers etc…

Visualising the Data

We can now plot them on a graph to see if we can visually identify any obvious trends among the data points.

CL <- rbind(CL1, CL2, CL3)

plot(CL, xlim = c(-78.3, -76), ylim = c(17.3, 18), main = 'Events')

There appears to be a clustering of two groups of incidents (one either side of the -77.4 Longitudinal line).

Next we’ll implement the K-means algorithm to verify if our observations are supported mathematically. Since the number of clusters ‘K’ is a hyper-parameter of the model, it is reasonable to follow our initial observation of K = 2. However, with our knowledge that the operational deployments are scheduled around three-shift days we’ll set K = 3 to test if we can identify three three corresponding clusters, one for each shift. After that we’ll visualise the clusters using ggplot2.

#Clustering with K=three

set.seed(101)

TwoD_Clust <- kmeans(CL, 3, iter.max = 10)#Assign the cluster to the varibale

CL$Group <- as.factor(TwoD_Clust$cluster)ggplot(CL, aes(x=CL$Longitude, y=CL$Latitude, color=CL$Group)) +

labs(x ='Longitude', y ='Latitude', title = 'Tri-Clustered Events') +

geom_point()

With K = 3 the algorithm was still able to identify highly distinguishable groups, however the two of the groups (1 & 3) looks forced. Let’s revert to K = 2 and visualise the results.

#Clustering with K=two

set.seed(100)

TwoD_Clust <- kmeans(CL, 2, iter.max = 10)#Assign the cluster to the varibale CL$Group <- as.factor(TwoD_Clust$cluster)ggplot(CL, aes(x=CL$Latitude, y=CL$Longitude, color=CL$Group)) +

labs(x ='Longitude', y ='Latitude', title = 'Bi-Clustered Events') +

geom_point()

Exploring the Data and Getting Creative

The groups still look as though they could be better fit, fortunately we’ve yet to add the third variable (time of incident) to our data. Possibly adding a third variable will help us be able to distinguish the groups better. Next we will compile all three variables Longitude, Latitude and Time into a dataframe and visualise it in 3D using the Plotly package to make an interactive 3D plot.

#Adding the third variable 'Time'

set.seed(41)

TCL1 <- data.frame(round(rnorm(20, mean = 10, sd = 1), 2))

names(TCL1) <- c('ETime') set.seed(42)

TCL2 <- data.frame(round(rnorm(50, mean = 23.5, sd = 1), 2))

names(TCL2) <- c('ETime') set.seed(43)

TCL3 <- data.frame(round(rnorm(130, mean = 3, sd = 1), 2))

names(TCL3) <- c('ETime')Event_Times <- rbind(TCL1, TCL2, TCL3) #Compiling all the data into a dataframe

Event_Data <- data.frame(rbind(CL1, CL2, CL3), Event_Times) #Using Plotly to visualise three dimensions

plot_ly(x =Event_Data$Longitude, y = Event_Data$Latitude, z= Event_Data$ETime,

type = 'scatter3d', mode = 'markers')

Rotate the Graph to view from different perspectives. Interactive 3D Scatter-plot

You can interact with and rotate the visualisation to view how the clusters look from different perspectives. Using this interactive 3D scatter-plot, we can now clearly identify three clusters of incidents. While the 2D plot obscured the variability of the data and suggested that deployments should be focused on two specific areas, it has now become obvious that ‘time of deployment’ should be a significant factor taken into consideration when planning routine deployments, and that ideally the available human resources should be divided into three teams, each deployed at specific times.

To further validate our observations we’ll conduct another K-Means analysis again with K= 3. With the output of the K-means function we will also be able to conduct a more detailed analysis of any trends that may be present in the data.

#Clustering the data with three variables and K=3

ThreeD_Clust <- kmeans(Event_Data, 3, iter.max = 10) Event_Data$Group <- as.factor(ThreeD_Clust$cluster) D32<- plot_ly(x = Event_Data$Longitude, y = Event_Data$Latitude, z= Event_Data$ETime,

type = 'scatter3d', mode = 'markers', color = Event_Data$Group) %>%

layout(title = '3D Clusters', scene = list(

xaxis = list(title ='Longitude'),

yaxis = list(title ='Latitude'),

zaxis = list(title ='Time Axis')

))

Rotate the Graph to view from different perspectives. Interactive Output of K-Means Cluster with K=3

You can interact with and rotate the visualisation to view how the clusters look from different perspectives. The algorithm has nicely identified three distinct clusters that can be used to identify optimal times and locations for effective operational deployments.

The Analysis and Interpretation

The work is not done yet. Next we must conduct an analysis of the output of the algorithm to formalise its results and convert them to actionable information that can be used to confidently deploy military resources.

#Viewing the output of the kmeans functionThreeD_ClustK-means clustering with 3 clusters of sizes 130, 20, 50Cluster means: Longitude Latitude ETime Group

1 -76.64654 17.64231 3.068308 1

2 -78.43600 17.86550 10.427000 3

3 -77.96940 17.73420 23.464600 2 Clustering vector:

[1] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3

[42] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1 1 1 1 1 1 1 1 1 1 1 1

[83] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

[124] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

[165] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Within cluster sum of squares by cluster:

[1] 134.22748 19.67019 68.32914 (between_SS / total_SS = 98.6 %)Available components:



[1] "cluster" "centers" "totss" "withinss" "tot.withinss"

[6] "betweenss" "size" "iter" "ifault"

From the output/results three pieces of information are of specific importance to our use case: 1) The cluster means or ‘centroids’. 2) The size of each cluster 3) Sum of Squares.

We have identified three clusters that identify opportune times and locations to which resources should be deployed in order to expect highest return on output. These are in the around points:

W-76*.64, N17*.64 around 3:00 a.m.

W-78*.43, N17*.86 around 10:45 a.m.

W-77*.96, N17*.73 around 11:45 p.m.

We can now plan deployments in and around these locations and times for maximum effectiveness.

2. The sizes of clusters 1, 2 & 3 are 130, 20 & 50 respectively (a ratio of 65:10:25). These numbers indicate the relative number of incidents that can be expected in each cluster. With this information we are able to appropriately distribute a team of 100 military personnel as follows 65 to cluster 1, 20 to cluster 2 and 25 to cluster 3. This mitigates inadvertent under-staffing and over-deploying to locations.

3. The within-cluster sum of squares represents the variability of clusters. Basically how well the model fits the data and how likely specific values are to be very different from the average. Large sums of squares would indicate that although deployments would be centered around specific locations and times they would still have to patrol significantly from those central areas and over an extended period of time. Our between group SS / total SS = 98.6%, indicating an extremely good fit of the model!

An example of this technique being used in real life can be found here

Side Note

It’s usually recommended that data be normalised/scaled prior to executing machine learning algorithms as differences in the ranges of variables can bias the performance of the model. I can confirm that that was not the case in this instance and there was no evidence of that occurring. In fact, after scaling the model tended to perform worse! (Feel free to rerun the code yourself and assess the results after scaling) - A subtle reminder of the art that exists in the science of machine learning. Also, setting the initial random iterations of the centroids to 10 appeared sufficient to produce a stable model with consistent results over several reruns of the algorithms. Time stamps were transformed to represent hours in a 24 hour day and latitude/ longitude values were converted from degrees* minutes’ format to degrees* and decimals.