# Probability Distributions and use cases
> Introduction to probability distributions with use cases.

- toc: true 
- badges: true
- comments: true
- author: Uday Paila
- categories: [probability, distribution, bernoulli, binomial, normal, poission, Geometric, lognormal]

# Discrete distributions


```python
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib import rcParams
# figure size in inches
rcParams['figure.figsize'] = 11.7,8.27
```

## Bernoulli distribution
A Bernoulli random variable has exactly two possible outcomes. We typically label one of these outcomes a "success" and the other outcome a "failure". We may also denote a success by 1 and a failure by 0.

The flip of a coin is modeled well by a Bernoulli distribution, as it is a single trial with a fixed nonzero probability of success (even if that probability is difficult to pin down if the coin is unfair).

> Note: Probability of success = p, mean = p, Var = p(1-p)


We can silumate using `np.random.random()`




```python
import numpy as np
np.random.random(1)
```

## Binomial Distribution   
The binomial distribution describes a sequence of identical, independent Bernoulli trials. That is, each trial has <b>the same probability of success</b>, and <b>the results of one trial do not affect any of the following trials</b>.  

let `Probability of success = p`  

\begin{align}
  \text{Probability of k success in n trails} = P(k) &=\binom{n}{k} p^k (1-p)^{n-k} \\
    \end{align}

<br>

> Note: mean = np, Var = np(1-p)

  
<br>

From above formual, we can tell given a 20 coin flips, what is the probability of getting 7 heads if getting a head is having probability of 0.35.  
    n = 20  
    k = 7  
    p = 0.35  
    Then,  
    P(7) = 0.18440118638  

We can simulate using `np.random.binomial`


```python
n = 20
p = 0.35
size=1000
np.random.seed(4)
vals = np.random.binomial(n, p, size)
sns.distplot(vals, kde=False, rug=False, color='red', label="number of heads in simulation of 20 coin flips")
plt.xlabel('No of Heads')
plt.ylabel('No of times occur out of 1000 times')
plt.legend()
```


```python
sns.distplot(vals, hist=False, kde=True, color='red', label="Probability of number of heads in simulation of 20 coin flips")
plt.xlabel('No of Heads')
plt.ylabel('Probability')
plt.legend()
```


```python
count_7 = sum(vals==7)
print("count", count_7)
prob = count_7/1000
print('probability', prob)
```

    count 179
    probability 0.179


Theoritical probability we got from formula is 0.1844 and now we got 0.179.

From above simulation we can also tell for probability if every any number of heads. we got a curve which is similar to normal distribution.  

  

> Warning: To check binomial distribution, It has to satisfy below conditions   
\- The trials are independent.   
\- The number of trials is fixed(n).   
\- Each trial outcome is classified as a success or failure.   
\- The probability of success(p) is the same for each trial.

  

#### Usecase-1
1. Let's take you are working in a food delivery company. Based on previous deliveries, the probability of delivering the wrong item is 0.0085. Per day, company delivers average of 1500 items. Loss per one wrong delivery is 100rs. Calculate the maximum loss we may get?

based on above info n = 1500, p = 0.0085


```python
np.random.seed(5)
wrong_deliveries = np.random.binomial(1500, 0.0085, 10000)
```


```python
sns.distplot(wrong_deliveries, hist=False, kde=True, color='red', label="Wrong Deliveries")
plt.hist(wrong_deliveries, density=True)
plt.xlabel('No of deliveries')
plt.ylabel('Probability')
plt.legend()
```


```python
max(wrong_deliveries)
```




    30




```python
kwargs = {'cumulative': True}
sns.distplot(wrong_deliveries, hist_kws=kwargs, kde_kws=kwargs, label='CDF of # of wrong delivery', color='red')
plt.legend()
```


```python
np.percentile(wrong_deliveries, 95)
```




    19.0



Based on CDF or using `np.percentile` we can tell how many wrong orders with a probability and the  we can calculate the loss. 

#### Usecase-2
2. Let's take you are working in a Manufacturing company. Based on previous data,  3% of items produced are defective. If we produce 5000 items a day, what is probabability to get a 4500 non defective items. or analyze the how many days it may needed to get 5 million non defective items? 

#### Usecase-3
3. Let's consider you are working in a tele-marketing company. Probability of converting a lead to sale is 6.5%, No of lead calls is 100 per day.. If you want to increase the revenue by some 10%, how many calls we have to make or how much conversion rate we need? How many employees we can recruit to increase the no of calls? 

## Poisson Distribution
The Poisson distribution is often useful for estimating the number of events in a large population over a unit of time.

Let's say, we have to calculate how many hits we will get to my website hourly. let's say probability of hit is 0.2 per hour.

We can model this even using the binomial RV if we have one hit or not in a hour but here we may get zero hits, 1 hit or some hour may give more than 1 hit. The problem with binomial is that it cannot contain more than 1 event in the unit of time (in this case, 1 hr is the unit time). The unit of time can only have 0 or 1 event. If we divid the unit of time into smaller parts, we can handle it i.e if we do n --> infinite ( i.e. p --> 0) in the Binomial distribution, we can model it.

The Poisson Distribution, doesn’t require you to know n or p. We are assuming n is infinitely large and p is infinitesimal. The only parameter of the Poisson distribution is the rate λ (the expected value of x).  

\begin{align}
P(k) = \frac{e^{-\lambda}\lambda^{k}} {k!} 
\end{align}

<br>

> Note: mean = Lambda, Var = Lambda

####  Usecase-1
1. Let's take you are working in E-Learning company. Based on previous data, on average comapany getting 7 queries per hour. What is the probability that getting 12 queries or more in the next hour. 


```python
lamda = 7
np.random.seed(12)
no_queries = np.random.poisson(lamda, size=20000)
```


```python
sns.distplot(no_queries, hist=False, kde=True, color='red', label="no of queries")
plt.hist(no_queries, density=True)
plt.xlabel('No of queries')
plt.ylabel('Probability')
plt.legend()
```


```python
print('probability', sum(no_queries>=12)/len(no_queries))
```

    probability 0.0545


## Geometric Distribution
The geometric distribution represents the number of failures before the first success in a sequence of Bernoulli trials.  

<br>

let `Probability of success = p` 

<br>

\begin{align}
  \text{Probability of having exactly k failures before the first success} = P(k) = (1-p)^{k}p \\
    \end{align}  
    
<br>
    
We can simulate it using `np.random.geometric`

#### Use Case-1
1. A programmer has a 90% chance of finding a bug every time he compiles his code, and it takes him two hours to rewrite his code every time he discovers a bug. What is the probability that he will finish his program by the end of his workday? Assume that a workday is 8 hours and that the programmer compiles his code immediately at the beginning of the day.

#### Use Case-2
2.. In cost-benefit analyses, such as a company deciding whether to fund research trials that, if successful, will earn the company some estimated profit, the goal is to reach a success before the cost outweighs the potential gain.

# Continuous distributions

## Normal distribution
The normal distribution is described by two parameters μ and σ, representing the mean and standard deviation of the random variable X respectively.
    
<br>

   \begin{align}
  \text{Probability Density Fn} = f(x) &= \dfrac{1}{\sqrt{2\pi} \sigma} e^{-\dfrac{(x-\mu)^2}{2 \sigma^2}} \\
    \end{align}
    
<br>
    
We can simulate it using `np.random.normal`


```python
normal_vals = np.random.normal(0, 5, 1000)
```


```python
sns.distplot(normal_vals, hist=False, kde=True, color='red', label="Normal Dist")
plt.hist(normal_vals, density=True)
plt.legend()
```


<br>

68-95-99.7 rule
<br>



## Exponential distribution
To predict the amount of waiting time until the next event (i.e., success, failure, arrival, etc.). You can thik similar to poission distribution. In poission distribution, we can predict how many events occur in a unit of time. In Exponential distribution, amout of time needed to event occur. 
If the number of events per unit time follows a Poisson distribution, then the amount of time between events follows the exponential distribution.

<br>


    
   \begin{align}
  \text{Probability Density Fn} = f(x) &= \lambda e^{-\lambda k} \\
    \end{align}

<br>


> Warning: X ~ Exp(0.3) is to remember that 0.3 is not a time duration, but it is an event rate, which is the same as the parameter λ in a Poisson process. When rate changes, it won't work. rate has to be constant


<br>



We can simulate it using `np.random.exponential`

<br>

#### Use case-1
1. At a call center, calls come in every 20 minutes on average. What is the approximate probability that no calls will come in for a 30 minute period?

The time between calls can be represented by an exponential distribution with Lambda=3, since one call every 20 minutes is 3 calls per hour. we have to get the probability that at least half an hour passes between calls


```python
np.random.seed(6)
calls_time = np.random.exponential(1/3, 10000)
```


```python
sum(vals>0.5)/len(vals)
```




    0.2292




```python
sns.distplot(calls_time, hist=False, kde=True, color='red', label="Calls time")
plt.hist(calls_time, density=True)
plt.legend()
```

#### Use case-2
2. A computer repair customer service takes an average of 3 days repair. How long (approximately, in days) should customer has to wait to pickup repaired product with 95% confidance?
    
    
The repair time can be represented by an exponential distribution with λ=1/3, the number of repairs per day.


```python
np.random.seed(8)
manf_time = np.random.exponential(3, 10000)
```


```python
manf_time
```




    array([ 6.20086514, 10.37717835,  6.1021323 , ...,  5.30842985,
            1.94993868,  3.36773582])




```python
n5p_value = np.percentile(manf_time, 95)
n5p_value
```




    8.912912006371394



 The customer should wait atleast 9 days to be 95% sure that the repair has done. 

## Log Normal
it describes a random variable whose logarithm is normally distributed.
    


```python

```

0237327de81314a4382b43e57c8b93454b727108
ipynb
Jupyter Notebook
_notebooks/2020-06-05-Distributions.ipynb
UdiBhaskar/practical-ml
17d7960a2e7e02ae8871868c8427f0105f7ea281
Apache-2.0
2020-12-09T09:13:07.000Z
2020-12-09T09:13:07.000Z
_notebooks/2020-06-05-Distributions.ipynb
UdiBhaskar/practical-ml
17d7960a2e7e02ae8871868c8427f0105f7ea281
Apache-2.0
2021-03-30T11:34:51.000Z
2022-02-26T08:54:35.000Z
_notebooks/2020-06-05-Distributions.ipynb
UdiBhaskar/practical-ml
17d7960a2e7e02ae8871868c8427f0105f7ea281
Apache-2.0
Qwen/Qwen-72B
1. YES
2. YES