<jupyter_start><jupyter_text>Task II  Problem Statement In the second task, the applicant is asked to code an algorithm for one-step prediction of future traffic in a single area. Formally, let us denote as $x_a$(t) the traffic observed at area _a_ during time interval _t_. At each time _t_, the algorithm receives as input a history $x_t$, ie., a vector of traffic values in past time intervals, upto _t_ included (the exact format of the history has to be selected by the applicant. The algorithm shall then produce as output an estimate $x_a$(t+1) of future _t+1_ in area _a_. The applicant shall run the algorithm to forecast traffic in the four geographical areas identified in Task I, during the week from December 16 to 22.   Reading datafiles for December 2013 Call Detail Records (CDRs)<jupyter_code>#Read Datafiles
df_cdrs_dec = pd.DataFrame({})
for i in range(1,23):
    df = pd.read_csv('../Data/CDRs_csv/sms-call-internet-mi-2013-12-%d.csv'%i , parse_dates=['datetime'])
    df_cdrs_dec = df_cdrs_dec.append(df)

df_cdrs_dec=df_cdrs_dec.fillna(0)   
df_cdrs_dec['sms'] = df_cdrs_dec['smsin'] + df_cdrs_dec['smsout']
df_cdrs_dec['calls'] = df_cdrs_dec['callin'] + df_cdrs_dec['callout']
df_cdrs_dec = df_cdrs_dec[['datetime', 'squareid', 'internet', 'sms', 'calls']].groupby(['datetime', 'squareid'], as_index=False).sum()
df_cdrs_dec.head()
df_cdrs_dec.tail()
df_cdrs_dec['hour'] = df_cdrs_dec.datetime.dt.hour+24*(df_cdrs_dec.datetime.dt.day-1)
df_cdrs_dec = df_cdrs_dec.set_index(['hour']).sort_index()<jupyter_output><empty_output><jupyter_text>Before directly jumping onto algorithm and modelling, First we will check Trend, Seasonality and Stationarity of our Time Series   To check Trend, Seasonality, Stationarity and modeling of our Time Series, we are first considering the area with highest network traffic ie. **squareid 5161**<jupyter_code>ydata = df_cdrs_dec[df_cdrs_dec.squareid==5161]['internet']
xdata = df_cdrs_dec[df_cdrs_dec.squareid==5161]['internet'].index

f = plt.figure()
plt.plot(xdata, ydata, color='black', linewidth=1, linestyle='-', label='Squareid 5161')
plt.title("NetworkTraffic - Squareid 5161")
plt.xlabel("Time [Total Hours]")
plt.ylabel("Number of Connections")
plt.xlim([0,528])
plt.ylim([0,40000])
plt.legend()
sns.despine()
plt.show()<jupyter_output><empty_output><jupyter_text>From the above figure, we can see the periodic nature of the time series with total number of connections. By inspection, the period is ~24 hrs.    Trend and Seasonality<jupyter_code>A Time Series basically has three components:  

1. Trend: The increasing or decreasing value in the Time Series

2. Seasonality: The repeating cycles in the Time Series

3. Noise: The random variations in the Time Series 

https://www.analyticsvidhya.com/blog/2015/12/complete-tutorial-time-series-modeling/<jupyter_output><empty_output><jupyter_text>In our case, we can see the daily seasonality (with no specific trend) which is consistent at every 24 hr period in the internet traffic activity.   Stationary Series<jupyter_code>The three basic criteria for Time Series to be classified as Stationary: 

1. The mean of the series should not be a function of time rather should be constant. 

2. The variance of the series should not be fuction of time rather should be constant. This property is also called as Homoscedicity. 

3. The covariance of the ith term and (i+m)th term should not be a function of time or the autocovariance that does not depend on time. 

Therefore, we cannot build a Time Series model until our series is stationary.<jupyter_output><empty_output><jupyter_text>Checking the Stationarity using Dickey-Fuller Test<jupyter_code>This is one of the statistical tests for checking the stationarity. Here, we consider the Null Hypothesis that the Time series is not stationary. The test results comprise of a Test Statistic and some Critical Values for different confidence intervals. If the 'Test Statistic' is less than 'Critical Value', we can reject the null hypothesis and can say that our Time Series is stationary. 

Also, most of the Time Series model work on the assumption that the timeseries is stationary.<jupyter_output><empty_output><jupyter_text>Check whether internet network traffic is stationary or not<jupyter_code>df = df_cdrs_dec.set_index(['datetime']).sort_index()
df_5161 = df.loc[df['squareid'] == 5161]
df_5161.head()
df_5161.tail()
df_5161 = df_5161[['internet']]
TS_5161 = df_5161
TS_5161_index = df_5161.index
from statsmodels.tsa.stattools import adfuller
def test_stationarity(timeseries):
    
    #Determing rolling statistics
    rolmean = ydata.rolling(24).mean()
    rolstd = ydata.rolling(24).std()

    #Plot rolling statistics:
    orig = plt.plot(timeseries, color='blue',label='Original')
    mean = plt.plot(rolmean, color='red', label='Rolling Mean')
    std = plt.plot(rolstd, color='black', label = 'Rolling Std')
    plt.legend(loc='best')
    plt.title('Rolling Mean & Standard Deviation')
    plt.show(block=False)
    
    #Perform Dickey-Fuller test:
    print ('Results of Dickey-Fuller Test:')
    dftest = adfuller(timeseries, autolag='AIC')
    dfoutput = pd.Series(dftest[0:4], index=['Test Statistic','p-value','#Lags Used','Number of Observations Used'])
    for key,value in dftest[4].items():
        dfoutput['Critical Value (%s)'%key] = value
    print (dfoutput)<jupyter_output><empty_output><jupyter_text>Run on Input Time Series<jupyter_code>test_stationarity(TS_5161)<jupyter_output><empty_output><jupyter_text>Comments & observations From the above fig, we can see there is small variation in the rolling values of mean and standard deviation and there is not specific continously increasing or decreasing trend. This is more of visual technique to check whether time series is stationary or not from graph. To verify, we can use Dickey-Fuller test results, Test statistic & Critical values for different confident intervals. Here, the Test static (-3.60) is smaller than 1% Critical values. Therefore, we can say with 99% confidence interval that this time series is stationary. Also, with the p-value is less than 0.05 so we reject the null hypothesis & confirms that the series is stationary.    Decomposition In this method, both trend and seasonality are modeled separately and remaning part of the series is returned.<jupyter_code>from statsmodels.tsa.seasonal import seasonal_decompose
decomposition = seasonal_decompose(TS_5161)

trend = decomposition.trend
seasonal = decomposition.seasonal
residual = decomposition.resid

plt.subplot(411)
plt.plot(ydata, label='Original')
plt.legend(loc='best')
plt.subplot(412)
plt.plot(trend, label='Trend')
plt.legend(loc='best')
plt.subplot(413)
plt.plot(seasonal,label='Seasonality')
plt.legend(loc='best')
plt.subplot(414)
plt.plot(residual, label='Residuals')
plt.legend(loc='best')
plt.tight_layout()<jupyter_output><empty_output><jupyter_text>Here, we can see Trend and Seasonality are seprated out of data. We can model our residuals.<jupyter_code>ts_decompose = residual
ts_decompose.dropna(inplace=True)
test_stationarity(ts_decompose)<jupyter_output><empty_output><jupyter_text>The Dickey-Fuller test also shows that the Test-Static value for residuals is also smaller than 1% Critical values. So, this time series is very close to stationary.  Eliminating Trend and Seasonality  **Trend** can be removed by transformation. Here, we will take Log Transformation to elimininate the Trend.<jupyter_code>TS_5161_log = np.log(TS_5161)<jupyter_output><empty_output><jupyter_text>Our time series has some daily **Seasonal** component, which can be removed. A time series where seasonal component has been removed is called seasonal stationary. There are different methods to correct seasonal component and eliminate seasonality : 1. Difference: Taking the difference at a particular time lag 2. Decomposition: Modelling both trend and seasonality and removing them from the model In our case, we have seasonal component at a lag of 24 hrs.  Differencing : We can remove the seasonal component by subtracting the value from previous day.<jupyter_code>TS_5161_log_diff = TS_5161_log - TS_5161_log.shift()
plt.plot(TS_5161_log_diff)
TS_5161_log_diff.dropna(inplace=True)
test_stationarity(TS_5161_log_diff)<jupyter_output><empty_output><jupyter_text>Dickey-Fuller test statistic is less than the 1% Critical value.  Forecasting the Time Series   Ques. A self-contained description of the proposed algorithm<jupyter_code>Forecasting the Time Series can be divided into two types: 

1. If we use only the previous values of the time series to predict its future values it is called Univariate Time Series Forcasting. 

2. If we use predictors values other than series values (Eg. Exogenous Variables) to forecast it is called Multivariate  Time Series Forecasting. 

In our case, we are considering only internet network traffic therefore it is Univariate Time Series Forecasting.<jupyter_output><empty_output><jupyter_text>Here, we will be using **ARIMA** model as forecasting method.<jupyter_code>ARIMA Model which stands for Autoregressive Integrated Moving Average is a genearlization of ARMA (Autoregressive Moving Average) model. It works on the idea that the information in the past values of the time series can alone be used to predict the future values. 

An ARIMA model is characterized by three terms: p, d, q

where,

p is the order of the AR term

q is the order of the MA term

d is the number of differencing required to make the time series stationary

Both Seasonal and Non Seasonal time series can be modeled with ARIMA. If a time series, has seasonal patterns, then we need to add seasonal terms and it becomes SARIMA ie. 'Seasonal ARIMA'.

https://www.machinelearningplus.com/time-series/arima-model-time-series-forecasting-python/
p and q terms: 

'p' is the order of the 'Auto Regressive' (AR) term. It refers to lags of dependent variable. And 'q' is the order of the 'Moving Average' (MA) term. It refers to the number of lagged forecast errors that should go into the ARIMA Model.<jupyter_output><empty_output><jupyter_text>ACF and PACF   These plots are basically used to determine the value of 'p' and 'q'<jupyter_code>AutoCorrelation Function (ACF):

A plot of auto-correlation of different lags is called ACF.

The plot summarizes the correlation of an observation with lag values. The x-axis shows the lag and the y-axis shows the correlation coeﬃcient between -1 and 1 for negative and positive correlation.

Partial AutoCorrelation Function (PACF): 

A plot of partial auto-correlation for different values of lags is called PACF.

The plot summarizes the correlations for an observation with lag values that is not accounted for by prior lagged observations.<jupyter_output><empty_output><jupyter_text>Plot ACF and PACF With No Differencing<jupyter_code>from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.graphics.tsaplots import plot_pacf 

fig, ax = plt.subplots(figsize=(8,3))
plot_acf(TS_5161.dropna(),ax=ax,lags=48);

fig, ax =  plt.subplots(figsize=(8,3))
plot_pacf(TS_5161.dropna(),ax=ax,lags=48);<jupyter_output><empty_output><jupyter_text>With Ist Order Differencing<jupyter_code>from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.graphics.tsaplots import plot_pacf 

fig, ax = plt.subplots(figsize=(8,3))
plot_acf(TS_5161.diff().dropna(),ax=ax,lags=48);

fig, ax =  plt.subplots(figsize=(8,3))
plot_pacf(TS_5161.diff().dropna(),ax=ax,lags=48);<jupyter_output><empty_output><jupyter_text>With IInd Order Differencing<jupyter_code>from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.graphics.tsaplots import plot_pacf 

fig, ax = plt.subplots(figsize=(8,3))
plot_acf(TS_5161.diff().diff().dropna(),ax=ax,lags=48);

fig, ax =  plt.subplots(figsize=(8,3))
plot_pacf(TS_5161.diff().diff().dropna(),ax=ax,lags=48);<jupyter_output><empty_output><jupyter_text>The right order of differencing is the minimum differencing required to get a near stationary series which roams around a defined mean and the ACF plot reaches to zero fairly quickly.If the autocorrelations are positive for many number of lags (10 or more), then the series needs further differencing. On the other hand, if the lag 1 autocorrelation itself is too negative, then the series is probably over-differenced.   For the above timeseries, looking at the autocorrelation plot for the IInd order differencing the lag goes into far negative zone more quickly, which indicates, the series might be over differenced. Therefore, we should consider ACF and PACF plot with Ist order of differencing / Without differencing.   AR term can be inspected by the PACF plot. We can observe, the PACF lag 1 and lag 2 is quite significant and is well above the significance line.  MA term can be inspected by ACF plot.PACF & ACF suggested that AR(2) and MA(2).  Model Building  As we know, we have a daily seasonality (with no specific trend) at every 24 hr period in the internet traffic activity. Therefore, we can either use **Auto-Arima or SARIMA (Seasonal Arima)**.The advantage of using Auto-Arima over ARIMA is that after data preprocessing we can skip ACF and PACF steps for manually determining / inspecting AR and MA values. It uses the AIC (Akaike Information Criteria) and BIC (Bayesian Information Criteria) values generated by trying different combinations of p,d & q values to fit the model.    Auto-Arima   Squareid 5161 (Area with the highest traffic in the four geographical areas)<jupyter_code>df_5161.head()
df_5161.tail()
### Train-Test split according to taskII

## Taking first 15 days of december as Training Set and 16-22 december week as Test set 
train = df_5161[df_5161.index < '2013-12-16 04:00:00']
test = df_5161[df_5161.index >= '2013-12-16 04:00:00']
train_internet_ts_log = np.log10(train['internet'])
### Performing Auto-Arima and Fit<jupyter_output><empty_output><jupyter_text>Ques. Exact statistics on training and/or execution time of the algorithm for squareid 5161<jupyter_code>import pmdarima as pm 
model = pm.auto_arima(df_5161, start_p=1, start_q=1,
                           max_p=5, max_q=5, m=24,
                           start_P=0,start_Q=0, seasonal=True,
                           d=0, D=0, trace=True,
                           error_action='ignore',  
                           suppress_warnings=True, 
                           stepwise=True,width_intercept=False)
output = model.fit(train_internet_ts_log)
print(output.summary().tables[0])
print(output.summary().tables[1])
print(model.aic())
forecast = output.predict(n_periods=169)
testCopy = test.copy()
testCopy['internet_ts_forecasted'] = np.power(10, forecast)<jupyter_output><empty_output><jupyter_text>Accuracy Mertics (Squareid 5161)<jupyter_code>from sklearn.metrics import mean_squared_error, mean_absolute_error
mean_absolute_error(y_true=testCopy['internet'],
                   y_pred=testCopy['internet_ts_forecasted'])
def mean_absolute_percentage_error(y_true, y_pred): 
    """Calculates MAPE given y_true and y_pred"""
    y_true, y_pred = np.array(y_true), np.array(y_pred)
    return np.mean(np.abs((y_true - y_pred) / y_true)) * 100
mean_absolute_percentage_error(y_true=testCopy['internet'],
                   y_pred=testCopy['internet_ts_forecasted'])<jupyter_output><empty_output><jupyter_text>Comments and Observations:  1. Around 24.59% MAPE implies that the model is about 75.41 % accurate in predicting the 16-22 week observations (squareid 5161). Although, this accuracy is not so good. 2. Probably, this is because we have hourly dataset which exhibits multiple-seasonalities. For example, In a particular day, we can have intra-daily seasonalities as well as seasonality at every 24 hrs between previous and next day. Also, these can be different on weekdays and weekends. 3. Generally, ARIMA does not handle multiple seasonalities quite well (https://stats.stackexchange.com/questions/360167/arima-model-configuration-for-hourly-forecasting-problem)   Ques. Plot reporting the superposed time series of (i) the original traffic (ii) the predicted traffic in the week from December 16 to 22 (Squareid 5161)<jupyter_code>axis = train['internet'].plot(label='Train Internet', figsize=(10, 6))
testCopy['internet'].plot(ax=axis, label='Test internet', alpha=0.7)
testCopy['internet_ts_forecasted'].plot(ax=axis, label='Forecasted internet', alpha=0.7)
axis.set_xlabel('Dates')
axis.set_ylabel('Number of Connections')
plt.legend(loc='best')
plt.title('Internet Network Traffic (squareid 5161)')
plt.show()
plt.close()<jupyter_output><empty_output><jupyter_text>Comments and Observations:   1. From the graph, we can see Dates on x-axis and Number of internet connections made during the month of December 2013. 2. The **BLUE line** belongs to network traffic for first 15 days used to train the model and **Red Line** belongs to network traffic used as test set for the week 16-22, December 2013. **Yellow line** belongs to forecasted value for that week. 3. Here, it is clearly visible that the Auto-ARIMA model forcast is much closer to the actual pattern during the weekdays than weekends.   Squareid 4159<jupyter_code>df_4159 = df.loc[df['squareid'] == 4159]
df_4159 = df_4159[['internet']]
df_4159.head()
df_4159.tail()
### Train-Test split according to taskII

## Taking first 15 days of december as Training Set and 16-22 december week as Test set 
train = df_4159[df_4159.index < '2013-12-16 04:00:00']
test = df_4159[df_4159.index >= '2013-12-16 04:00:00']
train_internet_ts_log = np.log10(train['internet'])
### Performing Auto-Arima and Fit<jupyter_output><empty_output><jupyter_text>Ques. Exact statistics on training and/or execution time of the algorithm for squareid 4159<jupyter_code>import pmdarima as pm 
model = pm.auto_arima(df_4159, start_p=1, start_q=1,
                           max_p=5, max_q=5, m=24,
                           start_P=0,start_Q=0, seasonal=True,
                           d=0, D=0, trace=True,
                           error_action='ignore',  
                           suppress_warnings=True, 
                           stepwise=True,width_intercept=False)
output = model.fit(train_internet_ts_log)
print(output.summary().tables[0])
print(output.summary().tables[1])
print(model.aic())
forecast = output.predict(n_periods=169)
testCopy = test.copy()
testCopy['internet_ts_forecasted'] = np.power(10, forecast)<jupyter_output><empty_output><jupyter_text>Accuracy Mertics (Squareid 4159)<jupyter_code>mean_absolute_error(y_true=testCopy['internet'],
                   y_pred=testCopy['internet_ts_forecasted'])
mean_absolute_percentage_error(y_true=testCopy['internet'],
                   y_pred=testCopy['internet_ts_forecasted'])<jupyter_output><empty_output><jupyter_text>Comments and Observation  1. Around 30.66% MAPE implies that the model is about 69.39 % accurate in predicting the 16-22 week observations (squareid 4159). 2. As, we saw earlier this squareid is near to squareid 4259 where famous Universities of Milan are present. There is high network traffic during weekdays than weekend and there is a lot of variability in network traffic. Also, as discussed earlier, we have hourly dataset which exhibits multiple-seasonalities. 3. Generally, ARIMA does not handle multiple seasonalities quite well (https://stats.stackexchange.com/questions/360167/arima-model-configuration-for-hourly-forecasting-problem)   Ques. Plot reporting the superposed time series of (i) the original traffic (ii) the predicted traffic in the week from December 16 to 22 (Squareid 4159)<jupyter_code>axis = train['internet'].plot(label='Train Internet', figsize=(10, 6))
testCopy['internet'].plot(ax=axis, label='Test internet', alpha=0.7)
testCopy['internet_ts_forecasted'].plot(ax=axis, label='Forecasted internet', alpha=0.7)
axis.set_xlabel('Dates')
axis.set_ylabel('Number of Connections')
plt.legend(loc='best')
plt.title('Internet Network Traffic (squareid 4159)')
plt.show()
plt.close()<jupyter_output><empty_output><jupyter_text>Comments and Observations:  1. From the graph, we can see Dates on x-axis and Number of internet connections made during the month of December 2013. 2. The **BLUE line** belongs to network traffic for first 15 days used to train the model and **Red Line** belongs to network traffic used as test set for the week 16-22, December 2013. **Yellow line** belongs to forecasted value for that week. 3. Here, it is clearly visible that there is a lot of variability in the network traffic. The traffic during the weekdays is much higher than weekends beacuse of Universities schedule. There is abrubt change in network traffic on weekdays following the weekends. Auto-ARIMA model is not able to capture those changes / differences.      Squareid 4556<jupyter_code>df_4556 = df.loc[df['squareid'] == 4556]
df_4556 = df_4556[['internet']]
df_4556.head()
df_4556.tail()
### Train-Test split according to taskII

## Taking first 15 days of december as Training Set and 16-22 december week as Test set 
train = df_4556[df_4556.index < '2013-12-16 04:00:00']
test = df_4556[df_4556.index >= '2013-12-16 04:00:00']
train_internet_ts_log = np.log10(train['internet'])
### Performing Auto-Arima and Fit<jupyter_output><empty_output><jupyter_text>Ques. Exact statistics on training and/or execution time of the algorithm for squareid 4556<jupyter_code>import pmdarima as pm 
model = pm.auto_arima(df_4556, start_p=1, start_q=1,
                           max_p=5, max_q=5, m=24,
                           start_P=0,start_Q=0, seasonal=True,
                           d=0, D=0, trace=True,
                           error_action='ignore',  
                           suppress_warnings=True, 
                           stepwise=True,width_intercept=False)
output = model.fit(train_internet_ts_log)
print(output.summary().tables[0])
print(output.summary().tables[1])
print(model.aic())
forecast = output.predict(n_periods=169)
testCopy = test.copy()
testCopy['internet_ts_forecasted'] = np.power(10, forecast)<jupyter_output><empty_output><jupyter_text>Accuracy Mertics (Squareid 4556)<jupyter_code>mean_absolute_error(y_true=testCopy['internet'],
                   y_pred=testCopy['internet_ts_forecasted'])
mean_absolute_percentage_error(y_true=testCopy['internet'],
                   y_pred=testCopy['internet_ts_forecasted'])<jupyter_output><empty_output><jupyter_text>Comments and Observation  1. Around 16.51% MAPE implies that the model is about 83.49 % accurate in predicting the 16-22 week observations (squareid 4159). This accuracy is more as compared to other squareids calculated above.     2. As, we saw earlier the squareid is near to squareid 4456 which is present in city centre and one of the most famous nightlife places in the Milan city. There is high network traffic during evening hours.   Ques. Plot reporting the superposed time series of (i) the original traffic (ii) the predicted traffic in the week from December 16 to 22 (Squareid 4556)<jupyter_code>axis = train['internet'].plot(label='Train Internet', figsize=(10, 6))
testCopy['internet'].plot(ax=axis, label='Test internet', alpha=0.7)
testCopy['internet_ts_forecasted'].plot(ax=axis, label='Forecasted internet', alpha=0.7)
axis.set_xlabel('Dates')
axis.set_ylabel('Number of Connections')
plt.legend(loc='best')
plt.title('Internet Network Traffic (squareid 4556)')
plt.show()
plt.close()<jupyter_output><empty_output><jupyter_text>Comments and Observations:  1. From the graph, we can see Dates on x-axis and Number of internet connections made during the month of December 2013. 2. The **BLUE line** belongs to network traffic for first 15 days used to train the model and **Red Line** belongs to network traffic used as test set for the week 16-22, December 2013. **Yellow line** belongs to forecasted value for that week. 3. Here, We see some sharp peaks in the graph on each day repeatedly. This increase in traffic is during evening hours. Auto-ARIMA model is able to capture this pattern quite well.       Squareid 5160<jupyter_code>df_5160 = df.loc[df['squareid'] == 5160]
df_5160 = df_5160[['internet']]
df_5160.head()
df_4556.tail()
### Train-Test split according to taskII

## Taking first 15 days of december as Training Set and 16-22 december week as Test set 
train = df_5160[df_5160.index < '2013-12-16 04:00:00']
test = df_5160[df_5160.index >= '2013-12-16 04:00:00']
train_internet_ts_log = np.log10(train['internet'])
### Performing Auto-Arima and Fit<jupyter_output><empty_output><jupyter_text>Ques. Exact statistics on training and/or execution time of the algorithm for squareid 5160<jupyter_code>import pmdarima as pm 
model = pm.auto_arima(df_5160, start_p=1, start_q=1,
                           max_p=5, max_q=5, m=24,
                           start_P=0,start_Q=0, seasonal=True,
                           d=0, D=0, trace=True,
                           error_action='ignore',  
                           suppress_warnings=True, 
                           stepwise=True,width_intercept=False)
output = model.fit(train_internet_ts_log)
print(output.summary().tables[0])
print(output.summary().tables[1])
print(model.aic())
forecast = output.predict(n_periods=169)
testCopy = test.copy()
testCopy['internet_ts_forecasted'] = np.power(10, forecast)<jupyter_output><empty_output><jupyter_text>Accuracy Mertics (Squareid 5160)<jupyter_code>mean_absolute_error(y_true=testCopy['internet'],
                   y_pred=testCopy['internet_ts_forecasted'])
mean_absolute_percentage_error(y_true=testCopy['internet'],
                   y_pred=testCopy['internet_ts_forecasted'])<jupyter_output><empty_output><jupyter_text>Comments and Observations: 1. Around 22.41% MAPE implies that the model is about 77.59 % accurate in predicting the 16-22 week observations (squareid 5160).  2. This squareid is near to the area(squareid 5161) with highest traffic during two month period. The model performed better for this squareid as compared to squareid 5161 because there is no surge in the Internet Network connections. Also, it is in the city centre of Milan.<jupyter_code>axis = train['internet'].plot(label='Train Internet', figsize=(10, 6))
testCopy['internet'].plot(ax=axis, label='Test internet', alpha=0.7)
testCopy['internet_ts_forecasted'].plot(ax=axis, label='Forecasted internet', alpha=0.7)
axis.set_xlabel('Dates')
axis.set_ylabel('Number of Connections')
plt.legend(loc='best')
plt.title('Internet Network Traffic (squareid 5160)')
plt.show()
plt.close()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09137918019174153, 'fraction_numerical': 0.03363025590699781, 'mean_word_length': 4.978113718411552, 'pattern_counts': {'":': 0, '<': 137, '<?xml version=': 0, '>': 137, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '33', 'dir': 'jupyter-structured-clean-dedup', 'id': '298520', 'license': 'MIT', 'n_tokens_mistral': 8842, 'n_tokens_neox': 8041, 'n_words': 2747, 'path': 'Time_Series_Forecasting_Task_II.ipynb', 'repo_name': 'Aujasvi-Moudgil/Forecasting-Mobile-Network-Traffic', 'size': '26494'}