BANSILAL RAMNATH AGARWAL CHARITABLE TRUST’S
VISHWAKARMA INSTITUTE OF TECHNOLOGY
(An Autonomous Institute affiliated to Savitribai Phule Pune University)
PUNE – 411037
Savitribai Phule Pune University
DEPARTMENT OF COMPUTER SCIENCE (SOFTWARE ENGINEERING)
Assignment No. – 3
Aim: Create a dashboard using Power BI/Tableau /Python for the dataset chosen in previous
assignments and perform following operations Connecting to data source and visualizing and
analysing data Connecting to data source and creating custom calculations, Deploying the
dashboards and reports to Power BI Service
Name – Vedant Nitin Alse
Roll No – 06
PRN No. – 12411179
Class – CSSE-A BATCH-1
Guide – Prof. Madhura Eknath Sanap
OBJECTIVE: To analyze network intrusion data using visual analytics, forecasting
techniques, and trend analysis to identify attack patterns, protocol behavior, and
predictive insights using the KDD dataset.
THEORY
Theory:
1. Visual Analy cs in Power BI/Tableau
Visual analy cs helps in iden fying suspicious pa erns in network traffic such as abnormal
spikes, unusual protocol usage, and a ack distribu on.
In this experiment, the KDD dataset was used, which contains network connec on records
labeled as normal or a ack types (e.g., Neptune, Smurf, Satan).
2. Forecas ng in Time-Series Data
Since the dataset does not contain mestamps, a synthe c me series was created by grouping
connec on dura ons into fixed windows (500 records per window).
Techniques used:
Moving Average (10-window, 30-window smoothing)
Linear Trend Forecas ng
This helps in predic ng future network behavior such as:
Increase in connec on dura on
Possible abnormal traffic spikes
3. Trend Analysis & Curve Fi ng
Trend analysis was applied between:
src_bytes → dst_bytes
Models used:
Linear
Logarithmic
Polynomial
Exponen al
Power
Evalua on metric:
R² Score (Goodness of Fit)
Procedure:
Step 1: Load Dataset into Power BI or Tableau
1. Open Power BI / Tableau Desktop.
2. Import the dataset (CSV, Excel, SQL, etc.).
3. Ensure the dataset contains a me column (Date/Year/Month) and numeric values.
Step 2: Create Visual Analy cs Dashboard
1. Add different visual elements such as:
o Time-Series Line Chart (for trends over me)
o Bar Chart (for categorical comparisons)
o Sca er Plot (for rela onships between variables)
o Heatmap (to show correla ons)
2. Format the visualiza ons by adding labels, tles, and legends.
3. Use filters and slicers to create an interac ve dashboard.
Step 3: Apply Forecas ng Model in Tableau/Power BI
1. Drag Date/Time to the X-axis and Numeric Values (e.g., Sales, Revenue) to the Y-axis.
2. In Tableau, open the Analy cs Pane and add Forecas ng.
3. In Power BI, use the Analy cs tab to enable Forecas ng.
4. Adjust the forecast length and confidence intervals.
Step 4: Iden fy Trends and Apply Curve Fi ng
1. Plot different trend lines:
o In Tableau, go to Trend Lines → Choose Linear, Logarithmic, Polynomial,
Exponen al, or Power.
o In Power BI, use the Analy cs Pane to add a trend line.
2. Compare R² values to iden fy the best-fi ng model.
3. Interpret the trends (e.g., Is the growth linear? Does it show exponen al increase?).
Step 5: Analyze Insights and Publish Dashboard
1. A ack Distribu on
Normal traffic highest (~67k), Neptune a ack dominates (~41k)
DoS a acks are most frequent → system mainly faces flooding a acks
2. Protocol Distribu on
TCP ~81.5%, UDP ~11.9%, ICMP ~6.6%
Most a acks occur over TCP → major vulnerability in TCP-based services
3. Source Bytes Analysis
TCP shows high varia on and outliers
TCP traffic is unpredictable and more a ack-prone
4. Service Analysis
HTTP, Private, Domain_u are top services
Web services are primary a ack targets
5. Correla on Analysis
Most features weakly correlated
Strong links: num_root, num_compromised
Indicates privilege escala on behavior
6. Time-Series Forecas ng
Slight decreasing trend (slope ≈ -0.072)
A acks are stable, not increasing rapidly
7. Curve Fi ng
Best model: Polynomial (R² ≈ 0.772)
Rela onship is non-linear → complex data pa ern
8. A ack vs Protocol
Neptune → TCP, Smurf → ICMP
A acks use specific protocols strategically
9. Difficulty Level
Mean ≈ 19.5 (high)
Dataset contains mostly complex a acks
Conclusion:
DoS attacks dominate network intrusion
TCP is the most vulnerable protocol
Attack patterns are stable but persistent
Data shows non-linear behavior → advanced models required
Code:
import warnings
[Link]("ignore")
import numpy as np
import pandas as pd
import [Link] as plt
import [Link] as gridspec
from [Link] import curve_fit
[Link]({
"[Link]": "#f8f9fa",
"[Link]": "#ffffff",
"[Link]": "#cccccc",
"[Link]": True,
"[Link]": 0.3,
"[Link]": 10,
"[Link]": 12,
"[Link]": "bold",
"[Link]": 10,
})
COLORS = ["#4e79a7", "#f28e2b", "#e15759", "#76b7b2",
"#59a14f", "#edc948", "#b07aa1", "#ff9da7",
"#9c755f", "#bab0ac"]
df = pd.read_csv("KDDTrain_clean.csv")
[Link] = [Link]().[Link]()
print(f" Dataset loaded: {[Link][0]:,} rows × {[Link][1]} columns\n")
# Figure 1
fig1, axes1 = [Link](2, 2, figsize=(14, 10))
[Link]("FIGURE 1 — Visual Analytics Dashboard (KDD Dataset)",
fontsize=15, fontweight="bold", y=0.98)
ax = axes1[0, 0]
attack_counts = df["attack_type"].value_counts().head(10)
bars = [Link](attack_counts.index[::-1], attack_counts.values[::-1],
color=COLORS[:10], edgecolor="white", linewidth=0.5)
ax.set_xlabel("Count")
ax.set_title("A. Top-10 Attack Types (Bar Chart)")
for bar, val in zip(bars, attack_counts.values[::-1]):
[Link](bar.get_width() + 200, bar.get_y() + bar.get_height()/2,
f"{val:,}", va="center", fontsize=8)
ax = axes1[0, 1]
proto = df["protocol_type"].value_counts()
[Link]([Link], labels=[Link], autopct="%1.1f%%",
colors=COLORS[:len(proto)], startangle=140,
wedgeprops={"edgecolor": "white", "linewidth": 1.5})
ax.set_title("B. Protocol Type Distribution (Pie Chart)")
ax = axes1[1, 0]
protocols = df["protocol_type"].unique()
box_data = [[Link][df["protocol_type"] == p, "src_bytes"].clip(upper=5000)
for p in protocols]
bp = [Link](box_data, labels=protocols, patch_artist=True, notch=True)
for patch, color in zip(bp["boxes"], COLORS):
patch.set_facecolor(color)
patch.set_alpha(0.7)
ax.set_ylabel("src_bytes (clipped at 5000)")
ax.set_title("C. Source Bytes by Protocol (Box Plot)")
ax = axes1[1, 1]
svc = df["service"].value_counts().head(10)
[Link]([Link], [Link], color=COLORS[:10],
edgecolor="white", linewidth=0.5)
ax.set_ylabel("Count")
ax.set_title("D. Top-10 Network Services (Bar Chart)")
ax.tick_params(axis="x", rotation=45)
fig1.tight_layout(rect=[0, 0, 1, 0.95])
[Link]("figure1_visual_analytics.png", dpi=150, bbox_inches="tight")
print(" Figure 1 saved → figure1_visual_analytics.png")
# Figure -2
fig2, ax2 = [Link](figsize=(12, 9))
[Link]("FIGURE 2 — Correlation Heatmap of Numeric Features",
fontsize=15, fontweight="bold", y=0.98)
numeric_cols = df.select_dtypes(include=[[Link]]).columns[:15] # top-15
corr = df[numeric_cols].corr()
im = [Link]([Link], cmap="RdBu_r", vmin=-1, vmax=1, aspect="auto")
ax2.set_xticks(range(len(numeric_cols)))
ax2.set_yticks(range(len(numeric_cols)))
ax2.set_xticklabels(numeric_cols, rotation=45, ha="right", fontsize=8)
ax2.set_yticklabels(numeric_cols, fontsize=8)
[Link](im, ax=ax2, shrink=0.8, label="Correlation")
for i in range(len(numeric_cols)):
for j in range(len(numeric_cols)):
val = [Link][i, j]
color = "white" if abs(val) > 0.6 else "black"
[Link](j, i, f"{val:.2f}", ha="center", va="center",
fontsize=6, color=color)
ax2.set_title("Pearson Correlation (first 15 numeric features)")
fig2.tight_layout(rect=[0, 0, 1, 0.95])
[Link]("figure2_correlation_heatmap.png", dpi=150, bbox_inches="tight")
print(" Figure 2 saved → figure2_correlation_heatmap.png")
# Figure -3
WINDOW = 500
ts = (df["duration"]
.groupby([Link] // WINDOW)
.mean()
.reset_index(drop=True))
[Link] = "time_window"
fig3, axes3 = [Link](2, 1, figsize=(14, 8), sharex=True)
[Link]("FIGURE 3 — Time-Series Forecasting on Connection Duration",
fontsize=15, fontweight="bold", y=0.98)
ax = axes3[0]
[Link]([Link], [Link], color=COLORS[0], alpha=0.5,
linewidth=0.8, label="Actual (mean duration per window)")
ma_10 = [Link](window=10, min_periods=1).mean()
ma_30 = [Link](window=30, min_periods=1).mean()
[Link]([Link], ma_10, color=COLORS[1], linewidth=2,
label="10-Window Moving Average")
[Link]([Link], ma_30, color=COLORS[2], linewidth=2,
label="30-Window Moving Average")
ax.set_ylabel("Mean Duration (sec)")
ax.set_title("A. Actual Data with Moving-Average Smoothing")
[Link](fontsize=9)
ax = axes3[1]
n = len(ts)
forecast_steps = 20
t = [Link](n)
coef = [Link](t, [Link], 1)
trend_line = [Link](coef, t)
t_future = [Link](n, n + forecast_steps)
forecast_vals = [Link](coef, t_future)
[Link](t, [Link], color=COLORS[0], alpha=0.5, linewidth=0.8,
label="Historical")
[Link](t, trend_line, color=COLORS[4], linewidth=2,
label=f"Linear Trend (slope={coef[0]:.4f})")
[Link](t_future, forecast_vals, color=COLORS[2], linewidth=2,
linestyle="--", marker="o", markersize=3,
label=f"Forecast (next {forecast_steps} windows)")
[Link](x=n-1, color="gray", linestyle=":", alpha=0.6)
ax.set_xlabel(f"Time Window Index (each window = {WINDOW} connections)")
ax.set_ylabel("Mean Duration (sec)")
ax.set_title("B. Linear Trend & Forecast")
[Link](fontsize=9)
fig3.tight_layout(rect=[0, 0, 1, 0.95])
[Link]("figure3_time_series_forecast.png", dpi=150, bbox_inches="tight")
print(" Figure 3 saved → figure3_time_series_forecast.png")
# Figure -4
x_raw = df["src_bytes"].[Link](float)
y_raw = df["dst_bytes"].[Link](float)
mask = (x_raw > 0) & (y_raw > 0)
x_all, y_all = x_raw[mask], y_raw[mask]
[Link](42)
if len(x_all) > 3000:
idx = [Link](len(x_all), 3000, replace=False)
x_s, y_s = x_all[idx], y_all[idx]
else:
x_s, y_s = x_all.copy(), y_all.copy()
order = [Link](x_s)
x_s, y_s = x_s[order], y_s[order]
x_grid = [Link](x_s.min(), x_s.max(), 500)
# ── Helper ──
def r2(y_true, y_pred):
ss_res = [Link]((y_true - y_pred) ** 2)
ss_tot = [Link]((y_true - [Link](y_true)) ** 2)
return 1 - ss_res / ss_tot if ss_tot != 0 else 0.0
def linear_fn(x, a, b): return a * x + b
def log_fn(x, a, b): return a * [Link](x) + b
def poly_fn(x, a, b, c): return a * x**2 + b * x + c
def exp_fn(x, a, b): return a * [Link](b * x)
def power_fn(x, a, b): return a * [Link](x, b)
models = {}
# 1. Linear
try:
p, _ = curve_fit(linear_fn, x_s, y_s, maxfev=5000)
y_pred = linear_fn(x_s, *p)
y_curve = linear_fn(x_grid, *p)
eq = f"y = {p[0]:.4f}·x + {p[1]:.1f}"
models["Linear"] = {"r2": r2(y_s, y_pred), "curve": y_curve, "eq": eq}
except Exception:
pass
# 2. Logarithmic
try:
p, _ = curve_fit(log_fn, x_s, y_s, maxfev=5000)
y_pred = log_fn(x_s, *p)
y_curve = log_fn(x_grid, *p)
eq = f"y = {p[0]:.2f}·ln(x) + {p[1]:.1f}"
models["Logarithmic"] = {"r2": r2(y_s, y_pred), "curve": y_curve, "eq": eq}
except Exception:
pass
# 3. Polynomial (degree 2)
try:
p, _ = curve_fit(poly_fn, x_s, y_s, maxfev=5000)
y_pred = poly_fn(x_s, *p)
y_curve = poly_fn(x_grid, *p)
eq = f"y = {p[0]:.6f}·x² + {p[1]:.4f}·x + {p[2]:.1f}"
models["Polynomial"] = {"r2": r2(y_s, y_pred), "curve": y_curve, "eq": eq}
except Exception:
pass
# 4. Exponential (with safe initial guess)
try:
p, _ = curve_fit(exp_fn, x_s, y_s, p0=[1, 1e-6],
maxfev=10000)
y_pred = exp_fn(x_s, *p)
y_curve = exp_fn(x_grid, *p)
eq = f"y = {p[0]:.2f}·e^({p[1]:.8f}·x)"
models["Exponential"] = {"r2": r2(y_s, y_pred), "curve": y_curve, "eq": eq}
except Exception:
models["Exponential"] = {"r2": float("nan"), "curve": None,
"eq": "Failed to converge"}
# 5. Power
try:
p, _ = curve_fit(power_fn, x_s, y_s, p0=[1, 0.5],
maxfev=10000)
y_pred = power_fn(x_s, *p)
y_curve = power_fn(x_grid, *p)
eq = f"y = {p[0]:.4f}·x^{p[1]:.4f}"
models["Power"] = {"r2": r2(y_s, y_pred), "curve": y_curve, "eq": eq}
except Exception:
models["Power"] = {"r2": float("nan"), "curve": None,
"eq": "Failed to converge"}
# ── Plot ──
fig4, axes4 = [Link](2, 3, figsize=(16, 10))
[Link]("FIGURE 4 — Trend Analysis: Curve Fitting (src_bytes → dst_bytes)",
fontsize=15, fontweight="bold", y=0.98)
for idx_m, (name, info) in enumerate([Link]()):
row, col = divmod(idx_m, 3)
ax = axes4[row, col]
[Link](x_s, y_s, s=4, alpha=0.3, color=COLORS[0], label="Data")
if info["curve"] is not None:
[Link](x_grid, info["curve"], color=COLORS[2], linewidth=2.5,
label=f"{name} fit")
r2_val = info["r2"]
r2_str = f"{r2_val:.4f}" if not [Link](r2_val) else "N/A"
ax.set_title(f"{name}\nR² = {r2_str}", fontsize=11)
ax.set_xlabel("src_bytes")
ax.set_ylabel("dst_bytes")
[Link](fontsize=8)
# add equation box
[Link](0.05, 0.95, info["eq"], transform=[Link],
fontsize=8, verticalalignment="top",
bbox=dict(boxstyle="round,pad=0.3", facecolor="#ffffcc",
edgecolor="#999999", alpha=0.8))
# ── Summary subplot ──
ax = axes4[1, 2]
[Link]("off")
summary_text = "━━━━ MODEL COMPARISON ━━━━\n\n"
best_name, best_r2 = None, -[Link]
for name, info in [Link]():
r2_val = info["r2"]
flag = ""
if not [Link](r2_val) and r2_val > best_r2:
best_r2, best_name = r2_val, name
r2_str = f"{r2_val:.4f}" if not [Link](r2_val) else "N/A"
summary_text += f" {name:14s} R² = {r2_str}\n"
summary_text += f"\n Best Fit: {best_name}\n (R² = {best_r2:.4f})"
[Link](0.1, 0.9, summary_text, transform=[Link],
fontsize=12, verticalalignment="top", family="monospace",
bbox=dict(boxstyle="round,pad=0.6", facecolor="#e8f5e9",
edgecolor="#43a047", alpha=0.9))
fig4.tight_layout(rect=[0, 0, 1, 0.95])
[Link]("figure4_trend_analysis.png", dpi=150, bbox_inches="tight")
print(" Figure 4 saved → figure4_trend_analysis.png")
# Figure -5
fig5, axes5 = [Link](1, 2, figsize=(14, 6))
[Link]("FIGURE 5 — Attack Category Analysis",
fontsize=15, fontweight="bold", y=0.98)
ax = axes5[0]
ct = [Link](df["attack_type"], df["protocol_type"])
top_attacks = df["attack_type"].value_counts().head(8).index
ct_top = [Link][top_attacks]
ct_top.plot(kind="barh", stacked=True, ax=ax, color=COLORS[:3],
edgecolor="white", linewidth=0.5)
ax.set_xlabel("Count")
ax.set_title("A. Attack Types by Protocol (Stacked Bar)")
[Link](title="Protocol", fontsize=8)
ax = axes5[1]
if "difficulty_level" in [Link]:
diff_levels = df["difficulty_level"].dropna()
[Link](diff_levels, bins=20, color=COLORS[1], edgecolor="white",
linewidth=0.5, alpha=0.85)
[Link](diff_levels.mean(), color=COLORS[2], linewidth=2,
linestyle="--", label=f"Mean = {diff_levels.mean():.1f}")
ax.set_xlabel("Difficulty Level")
ax.set_ylabel("Frequency")
ax.set_title("B. Distribution of Difficulty Level")
[Link]()
else:
[Link](0.5, 0.5, "Column not found", ha="center", va="center",
transform=[Link], fontsize=14)
fig5.tight_layout(rect=[0, 0, 1, 0.95])
[Link]("figure5_attack_analysis.png", dpi=150, bbox_inches="tight")
print(" Figure 5 saved → figure5_attack_analysis.png")
print("\n" + "=" * 60)
print(" SUMMARY OF ALL OUTPUTS")
print("=" * 60)
print(f" Dataset : KDDTrain_clean.csv")
print(f" Rows × Cols : {[Link][0]:,} × {[Link][1]}")
print(f" Attack Types : {df['attack_type'].nunique()}")
print()
print(" Figures Generated:")
print(" 1. figure1_visual_analytics.png — Bar, Pie, Box, Service charts")
print(" 2. figure2_correlation_heatmap.png — Correlation heatmap (15 features)")
print(" 3. figure3_time_series_forecast.png — Moving Avg & Linear Forecast")
print(" 4. figure4_trend_analysis.png — 5 Curve Fits + R² comparison")
print(" 5. figure5_attack_analysis.png — Stacked bar & Difficulty hist")
print()
print(" Curve-Fitting Results (src_bytes → dst_bytes):")
for name, info in [Link]():
r2_val = info["r2"]
star = " ◀ BEST" if name == best_name else ""
r2_str = f"{r2_val:.4f}" if not [Link](r2_val) else "N/A"
print(f" {name:14s} R² = {r2_str}{star}")
print("=" * 60)
[Link]()
Output: