Created
April 19, 2022 01:44
-
-
Save ribsy/76bfff5897322450819d8d0e0ad143ea to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
source("manifesto_functions.R") | |
################## | |
### Get Small Data | |
#Engineer One and Two Remediation Rate Beliefs | |
eng_one <- c(4,7) #Median and 90% Stretch | |
eng_two <- c(2,4) | |
# 4 fix, 7 stretch fix, out of 10 | |
GetBeliefsHits(eng_one[1], eng_one[2],10) | |
MakeBetaGraph(1.96,2.78,"Vuln Fix Rate","Plausibility", | |
"Sec Eng Beliefs","4 Fix, 7 Max, out of 10") | |
# 2 Fixes, 4 Stretch Fixes, out of 10 | |
GetBeliefsHits(eng_two[1], eng_two[2],10) | |
MakeBetaGraph(2.07,7.32,"Vuln Fix Rate","Plausibility", | |
"Sec Eng 2's Beliefs","2 Fix, 4 Max, out of 10") | |
### Data Functions for MakeBetaGraph() ### | |
# Generate prior distribution data using SME shape parameters | |
prior <- distribution_beta(1000,2.07,7.32) | |
# Look at first 20 results | |
head(prior, 20) | |
# Get 89% Credible Interval | |
ci(prior, method="HDI") | |
# Add density for graphing | |
prior <- prior %>% estimate_density() | |
# Print out some results | |
head(prior, 5) | |
############################# | |
### Scoring Beliefs With Data | |
opened_dates <- c("2020-07-25","2020-08-01","2020-08-03","2020-08-03", | |
"2020-08-03","2020-08-05","2020-08-05","2020-08-30", | |
"2020-09-12","2020-09-20","2020-09-23") | |
closed_dates <- c("2020-07-29","2020-08-05","2020-08-06","2020-08-06", | |
"2020-09-03","2020-09-13","2020-09-25") | |
#Get Shape Parameters For Each Engineer | |
eng_one <- GetBeliefsHits(4,7,10) | |
eng_two <- GetBeliefsHits(2,4,10) | |
#Get counts of opened and closed dates and their delta | |
opened <- length(opened_dates) | |
closed <- length(closed_dates) | |
delta <- opened - closed | |
# Compare each engineer's belief to the vulnerability data – no bias | |
raw_score <- ScoreBetaBeliefs(bias = c(.5,.5), first_belief = eng_one, | |
second_belief = eng_two, hits = closed, misses = delta ) | |
# Compare again, but bias the data toward the second engineer: .3, .7 | |
favor_eng2_score <- ScoreBetaBeliefs(bias = c(.3,.7), | |
first_belief = eng_one, second_belief = eng_two, | |
hits = closed, misses = delta ) | |
# Print out the unbiased Score | |
raw_score | |
# Print out the biased score | |
favor_eng2_score | |
# Vuln Data Central Tendency – date ratios | |
closed/opened | |
########################### | |
### Graph The Updated Model | |
# Bayesian Updating - Data + Beliefs | |
updated_hits <- eng_one[1] + closed #update | |
updated_misses <- eng_one[2] + delta #update | |
MakeBetaGraph(hit = updated_hits, miss = updated_misses, | |
"Vuln Fix Rate","Plausibility","Bayesian Updating Example", | |
"Eng 1 Beliefs + Data") | |
######################### | |
### Predicting The Future | |
# What’s A Plausible Remediation Rate For 22 Extreme Vulns? | |
future_count <- 22 | |
vpred <- GetVulnPredictions(updated_hits, updated_misses, future_count) | |
### Code Inside GetVulnPredictions | |
# Priors + Data | |
beta_vals <- c(updated_hits, updated_misses) | |
# Store as list from 0 to 22 | |
future_list = 0:future_count | |
# LearnBayes predictive function: uses beta prior and binomial data output | |
prob_future = pbetap(beta_vals, future_count, future_list) | |
# This call produces the list seen below. | |
round(cbind(future_list, prob_future), digits=3) | |
### 90% Most Probable Results | |
discint(cbind(vpred[,1], vpred[,2]), .9) | |
beta_probs = rbeta(n=1000, updated_hits, updated_misses) | |
closed_counts = rbinom(n=1000, size=future_count, prob=beta_probs) | |
table(closed_counts) | |
closed_freq = table(closed_counts) | |
closed_props = closed_freq/sum(closed_freq) | |
plot(closed_props, type="h", xlab="Number Closed", | |
las=1, lwd=3, ylab="Probability Closed") | |
############################## | |
### Wrapping Up Basic Burndown | |
# Get prior beliefs in shape parameter form | |
eng_one <- GetBeliefsHits(4,7,10) | |
# Raw Data | |
opened_dates <- c("2020-07-25","2020-08-01","2020-08-03","2020-08-03", | |
"2020-08-03","2020-08-05","2020-08-05","2020-08-30", | |
"2020-09-12","2020-09-20","2020-09-23") | |
closed_dates <- c("2020-07-29","2020-08-05","2020-08-06","2020-08-06", | |
"2020-09-03","2020-09-13","2020-09-25") | |
# Count Closed | |
closed <- length(closed_dates) | |
# Count left opened | |
delta <- length(opened_dates) - closed | |
# Bayesian Update, beliefs + data | |
updated_hits <- eng_one[1] + closed | |
updated_misses <- eng_one[2] + delta | |
# Create a graph that is a mesh of the above | |
MakeBetaGraph(hit = updated_hits, miss = updated_misses, | |
"Vuln Fix Rate","Plausibility","Bayesian Updating Example", | |
"Eng 1 Beliefs + Data") | |
### Bayes Burndown Curves | |
# Bayes Burndown Curve (black): Eng1 Beliefs + Data | |
curve(dbeta(x, closed + eng_one[1], delta + eng_one[2]), from=0, to=1, | |
xlab="Burndown Rate", ylab="Plausibility",col=1, lwd=4, las=1) | |
# Actual Vuln Data (Dates) Curve (red) | |
curve(dbeta(x, closed + 1, delta + 1), add=TRUE, col=2,lwd=4) | |
# Engineer 1 Beliefs (green) | |
curve(dbeta(x, eng_one[1], eng_one[2]), add=TRUE, col=3, lwd=4) | |
# Engineer 2 Beliefs (blue) | |
curve(dbeta(x, eng_two[1], eng_two[2]), add=TRUE, col=4, lwd=4) | |
#Legend | |
legend("topright", c("Engineer 2","Engineer 1", "Real Data", | |
"Bayesian Update"), col=c(4,3, 2, 1), lwd=c(3,3, 3, 3)) | |
###################################### | |
### Building A Bayesian Burndown Chart | |
# Jan includes Prior + first months data. | |
vulnData <- tibble( | |
yaxis = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", | |
"Oct", "Nov", "Dec"), | |
hits = c( 2, 4, 13, 4, 5, 12, 17, 7, 4, 3, 2, 4), | |
misses = c(12, 11, 10, 9, 8, 7, 6, 5, 14, 13, 12, 16) | |
) | |
# Encode Prior Beliefs | |
eng_one_prior <- GetBeliefsHits(eng_one[1], eng_one[2],10) | |
# Build Tidy Data Frame for Visualization | |
eng_risk <- MakeVulnData(vulnData, eng_one_prior) | |
# Make Visualization | |
MakeRidgeChart(eng_risk, | |
"Extreme Vulnerability Burndown Rates - One Week SLA", | |
"One Team Baselining Month By Month", | |
"Baseline Rate", | |
"Months", | |
"Time Frame") | |
### MakeVulnData() and MakeBurnData() Availble in manifesto_functions.R | |
# Get beta shape parameters from eng_ris for january | |
jan <- eng_risk %>% filter(yaxis == "Jan") %>% | |
select(closed, misses) %>% distinct() | |
# Generate 1,000 random probabilities constrained by shape params | |
jan_dist <- rbeta(10000, jan$closed, jan$misses) | |
# Get the 89% Highest Density Interval | |
jan_hdi <- ci(jan_dist, method = "HDI") | |
jan_hdi | |
# Get the shape parameters for Dec | |
dec <- eng_risk %>% filter(yaxis == "Dec") %>% | |
select(closed, misses) %>% distinct() | |
# Generate 1000 probabilities constrained by shape parameters | |
dec_dist <- rbeta(1000, dec$closed, dec$misses) | |
# Get the HDI | |
dec_hdi <- ci(dec_dist, method = "HDI") | |
dec_hdi | |
# Get Diff Between Months | |
diff_dist <- dec_dist - jan_dist | |
# How much of Dec is credibly within Jan? | |
rope(diff_dist) | |
##################### | |
### Are We Improving? | |
# Best central tendency point estimates | |
map_estimate(jan_dist) | |
map_estimate(dec_dist) | |
# Simple/Quick Plots | |
plot(density(jan_dist)) | |
plot(density(dec_dist)) | |
GetRope(eng_risk, "Jun", "Dec") | |
########################## | |
### Final: Comparing Teams | |
# Build Team One Data Frame | |
teamOneData <- tibble(yaxis = "Team 1", | |
hits = c(10,24,46, 160), | |
misses = c(20,20,20,5), | |
legend = c("Q1", "Q2", "Q3", "Q4")) | |
# Codify Eng One Beliefs | |
prior <- GetBeliefsHits(eng_one[1], eng_one[2],10) | |
# Create Posterior Distribution | |
team1 <- MakeVulnData(teamOneData, prior) | |
# Build TEam Two Data Frame | |
teamTwoData <- tibble(yaxis = "Team 2", | |
hits = c(10,15,20, 40), | |
misses = c(20,30,40,80), | |
legend = c("Q1", "Q2", "Q3", "Q4")) | |
# Codify Eng Two Beliefs | |
prior <- GetBeliefsHits(eng_two[1], eng_two[2],10) | |
# Create Posterior Distribution | |
team2 <- MakeVulnData(teamTwoData, prior) | |
# Combine Posteriors Into One Data Frame row by row | |
eng_risk <- rbind(team1, team2) | |
# Make Combined Chart | |
MakeRidgeChart2(eng_risk, | |
"Extreme Vulnerability Burndown Rates - One Week SLA", | |
"Q1 To Q4 Difference", | |
"Baseline Rate", "Teams", | |
"Time Frame") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment