- Posted on
- • Artificial Intelligence
Artificial Intelligence Python Case Studies
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
AI in the Shell: 4 Python Case Studies You Can Run from Bash
If you’ve been curious about Artificial Intelligence but assumed it required massive clusters or complex tooling, this post is for you. We’ll show how to solve real problems with Python-based AI/ML that you can install, run, and automate from a plain Linux terminal. No mystery boxes—just packages you can install with apt, dnf, or zypper and scripts you can schedule with cron.
What you’ll get:
Why AI + Linux/Bash is a practical combo
A minimal, cross-distro setup for Python ML
Four case studies with runnable code
Bash-friendly workflows for training, predicting, and automating
Why AI from the command line?
It’s reproducible and scriptable. Bash keeps things explicit and automatable (shell scripts, cron, systemd timers).
It’s portable. Python and Linux packages are available across distros.
It’s cost-effective. You can do a lot with CPU-only algorithms (scikit-learn, statsmodels) on commodity hardware.
It’s maintainable. Small, focused scripts integrate well with existing tooling (git, SSH, CI/CD).
Prerequisites: Install the basics
Install system dependencies and Python tooling. Use your package manager:
- Debian/Ubuntu (apt):
sudo apt update
sudo apt install -y python3 python3-venv python3-pip build-essential python3-dev git curl
- Fedora/RHEL/CentOS Stream (dnf):
sudo dnf install -y python3 python3-pip gcc gcc-c++ make python3-devel git curl
- openSUSE (zypper):
sudo zypper refresh
sudo zypper install -y python3 python3-pip gcc gcc-c++ make python3-devel git curl
Create a project and virtual environment:
mkdir -p ~/ai-lab && cd ~/ai-lab
python3 -m venv .venv
source .venv/bin/activate
Install Python packages (works the same on all distros once the venv is active):
pip install -U pip wheel
pip install numpy pandas scikit-learn joblib statsmodels matplotlib seaborn jupyterlab
Tip: Keep this venv dedicated to your AI scripts to avoid dependency conflicts.
Case Study 1: Predictive Maintenance from Sensor CSVs
Problem: Given equipment sensor data, predict if a failure is likely soon.
Approach: Train a RandomForest classifier on historical data, then run a CLI script to flag new records.
Train script (auto-generates synthetic data if none is provided):
#!/usr/bin/env python3
# file: train_predictive_maintenance.py
import argparse, os
import numpy as np, pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report
from joblib import dump
def make_synthetic_csv(path, n=2000, seed=42):
rng = np.random.default_rng(seed)
temp = rng.normal(70, 10, n)
vib = rng.normal(0.3, 0.1, n)
rpm = rng.normal(1500, 300, n)
# Simple failure rule (hidden pattern)
fail_prob = (temp > 80).astype(int)*0.3 + (vib > 0.4).astype(int)*0.4 + (rpm > 1700).astype(int)*0.2
y = (rng.random(n) < fail_prob).astype(int)
pd.DataFrame({"temp": temp, "vibration": vib, "rpm": rpm, "failed": y}).to_csv(path, index=False)
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--data", default="sensors.csv")
ap.add_argument("--model", default="models/maint_rf.joblib")
args = ap.parse_args()
os.makedirs(os.path.dirname(args.model), exist_ok=True)
if not os.path.exists(args.data):
print(f"[i] No {args.data} found; generating synthetic dataset...")
make_synthetic_csv(args.data)
df = pd.read_csv(args.data)
X = df[["temp", "vibration", "rpm"]]
y = df["failed"]
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.2, random_state=0, stratify=y)
clf = RandomForestClassifier(n_estimators=200, random_state=0, n_jobs=-1)
clf.fit(Xtr, ytr)
yhat = clf.predict(Xte)
print(classification_report(yte, yhat, digits=3))
dump(clf, args.model)
print(f"[✓] Model saved to {args.model}")
if __name__ == "__main__":
main()
Predict script (reads a CSV and appends a “risk” prediction):
#!/usr/bin/env python3
# file: predict_risk.py
import argparse, pandas as pd
from joblib import load
ap = argparse.ArgumentParser()
ap.add_argument("--model", default="models/maint_rf.joblib")
ap.add_argument("--in-csv", required=True)
ap.add_argument("--out-csv", default="predictions.csv")
args = ap.parse_args()
clf = load(args.model)
df = pd.read_csv(args.in_csv)
proba = clf.predict_proba(df[["temp","vibration","rpm"]])[:,1]
out = df.copy()
out["failure_risk"] = proba
out.to_csv(args.out_csv, index=False)
print(f"[✓] Wrote {args.out_csv}")
Run it from Bash:
python train_predictive_maintenance.py
head -n 5 sensors.csv > incoming.csv
python predict_risk.py --in-csv incoming.csv --out-csv risk.csv
column -s, -t < risk.csv | sed -n '1,6p'
Actionable points:
Keep the model file under version control with metadata (date, data snapshot).
Use cron to score new sensor batches periodically.
Start simple (RandomForest), measure, then iterate.
Case Study 2: NLP Ticket Triage (No Deep Learning Required)
Problem: Route support tickets to the right queue (billing, bug, feature, etc.) to save human time.
Approach: Train a TF‑IDF + LinearSVC pipeline on historical tickets. This is fast and runs well on CPU.
Train + evaluate:
#!/usr/bin/env python3
# file: train_ticket_triage.py
import argparse, os, pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.pipeline import Pipeline
from sklearn.svm import LinearSVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from joblib import dump
def maybe_make_synth(path):
if os.path.exists(path): return
rows = [
("My invoice is wrong, double charged", "billing"),
("App crashes on login with error 500", "bug"),
("Can you add dark mode?", "feature"),
("Refund didn’t arrive", "billing"),
("Button misaligned on mobile", "bug"),
("Export to CSV would be helpful", "feature"),
("How do I reset my password?", "other"),
("Payment failed at checkout", "billing"),
("Search results are empty though items exist", "bug"),
("Support multi-language UI", "feature"),
]
pd.DataFrame(rows, columns=["text","label"]).to_csv(path, index=False)
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--data", default="tickets.csv")
ap.add_argument("--model", default="models/triage_svc.joblib")
args = ap.parse_args()
os.makedirs(os.path.dirname(args.model), exist_ok=True)
maybe_make_synth(args.data)
df = pd.read_csv(args.data)
Xtr, Xte, ytr, yte = train_test_split(df["text"], df["label"], test_size=0.3, random_state=1, stratify=df["label"])
pipe = Pipeline([
("tfidf", TfidfVectorizer(min_df=1, ngram_range=(1,2))),
("clf", LinearSVC())
])
pipe.fit(Xtr, ytr)
yhat = pipe.predict(Xte)
print(classification_report(yte, yhat, digits=3))
dump(pipe, args.model)
print(f"[✓] Saved {args.model}")
if __name__ == "__main__":
main()
Predict from stdin or a file:
#!/usr/bin/env python3
# file: classify_ticket.py
import argparse, sys
from joblib import load
ap = argparse.ArgumentParser()
ap.add_argument("--model", default="models/triage_svc.joblib")
ap.add_argument("--text", help="Ticket text; if omitted, read stdin")
args = ap.parse_args()
pipe = load(args.model)
text = args.text if args.text else sys.stdin.read()
print(pipe.predict([text])[0])
Bash usage:
python train_ticket_triage.py
echo "Users are billed twice this month" | python classify_ticket.py
python classify_ticket.py --text "App freezes when uploading files"
Actionable points:
Maintain a labeled CSV; even a few hundred rows can unlock strong gains.
Retrain periodically as product and language evolve.
Add simple rules on top of the ML output for high-confidence auto-routing.
Case Study 3: Demand Forecasting with ARIMA
Problem: Forecast daily sales to plan inventory and staffing.
Approach: Use ARIMA via statsmodels. It’s interpretable and works well on many time series.
Forecast script:
#!/usr/bin/env python3
# file: forecast_sales.py
import argparse, os, pandas as pd, numpy as np
from datetime import datetime, timedelta
from statsmodels.tsa.arima.model import ARIMA
def maybe_make_synth(path, days=180, seed=7):
if os.path.exists(path): return
rng = np.random.default_rng(seed)
start = datetime(2024,1,1)
dates = [start + timedelta(days=i) for i in range(days)]
base = 200 + 10*np.sin(np.arange(days)/7*2*np.pi) # weekly seasonality-ish
noise = rng.normal(0, 8, days)
trend = np.linspace(0, 20, days)
sales = np.clip(base + noise + trend, 50, None).round()
pd.DataFrame({"date": dates, "sales": sales.astype(int)}).to_csv(path, index=False)
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--data", default="daily_sales.csv")
ap.add_argument("--out", default="sales_forecast.csv")
ap.add_argument("--horizon", type=int, default=14)
args = ap.parse_args()
maybe_make_synth(args.data)
df = pd.read_csv(args.data, parse_dates=["date"]).sort_values("date")
series = df.set_index("date")["sales"]
model = ARIMA(series, order=(3,1,2))
fit = model.fit()
fc = fit.get_forecast(steps=args.horizon)
pred = fc.predicted_mean
conf = fc.conf_int(alpha=0.2) # 80% interval
out = pd.DataFrame({
"date": pd.date_range(series.index[-1] + pd.Timedelta(days=1), periods=args.horizon, freq="D"),
"forecast": pred.values,
"lo80": conf.iloc[:,0].values,
"hi80": conf.iloc[:,1].values
})
out.to_csv(args.out, index=False)
print(f"[✓] Wrote {args.out}")
if __name__ == "__main__":
main()
Run it and preview:
python forecast_sales.py --horizon 21
column -s, -t < sales_forecast.csv | sed -n '1,6p'
Actionable points:
Start with ARIMA; if residuals look bad, consider SARIMA or Prophet later.
Forecast at the granularity you can act on (daily/weekly).
Compare against a naive baseline (last week’s average) to validate lift.
Case Study 4: Log Anomaly Detection (Isolation Forest)
Problem: Spot unusual log lines (potential incidents or attacks) without hand-crafting every rule.
Approach: Extract simple numeric features from logs and fit IsolationForest to “normal” data.
Script:
#!/usr/bin/env python3
# file: detect_log_anomalies.py
import argparse, re, numpy as np, pandas as pd
from sklearn.ensemble import IsolationForest
def featurize(lines):
feats = []
for ln in lines:
ln = ln.rstrip("\n")
tokens = ln.split()
length = len(ln)
uniq = len(set(tokens))
digits = sum(ch.isdigit() for ch in ln)
uppers = sum(ch.isupper() for ch in ln)
ratio_digits = digits / max(1, length)
ratio_uppers = uppers / max(1, length)
hour = -1
m = re.search(r"\b(\d{2}):\d{2}:\d{2}\b", ln)
if m:
hour = int(m.group(1))
feats.append([length, uniq, ratio_digits, ratio_uppers, hour])
return np.array(feats)
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--train", help="Path to normal logs for training")
ap.add_argument("--score", help="Path to logs to score", required=True)
ap.add_argument("--out", default="anomalies.txt")
args = ap.parse_args()
if args.train:
with open(args.train) as f: train_lines = f.readlines()
else:
train_lines = [] # if none provided, fall back to first 200 of score
with open(args.score) as f: score_lines = f.readlines()
if not train_lines:
train_lines = score_lines[: min(200, len(score_lines))]
Xtr = featurize(train_lines)
Xte = featurize(score_lines)
iso = IsolationForest(n_estimators=200, contamination=0.02, random_state=0)
iso.fit(Xtr)
preds = iso.predict(Xte) # -1 = anomaly
anomalies = [ln for ln, p in zip(score_lines, preds) if p == -1]
with open(args.out, "w") as f:
f.writelines(anomalies)
print(f"[✓] Found {len(anomalies)} anomalies. Saved to {args.out}")
if __name__ == "__main__":
main()
Example:
# Use a system log for training or testing
python detect_log_anomalies.py --train /var/log/syslog --score /var/log/syslog --out anomalies.txt 2>/dev/null || \
python detect_log_anomalies.py --score /var/log/messages --out anomalies.txt
sed -n '1,10p' anomalies.txt
Actionable points:
Tune contamination (%) to control how many lines are flagged.
Pipe anomalies into alerting (mailx, Slack webhook, or journald).
Add domain-specific features (e.g., HTTP status codes, request sizes).
Automate it with Bash and cron
- Environment:
cd ~/ai-lab
source .venv/bin/activate
export PYTHONUNBUFFERED=1
- Example cron entry to forecast every morning at 6 AM:
crontab -e
# Add:
0 6 * * * . $HOME/ai-lab/.venv/bin/activate && python $HOME/ai-lab/forecast_sales.py --horizon 14 >> $HOME/ai-lab/cron.log 2>&1
- Keep logs:
tail -f ~/ai-lab/cron.log
Conclusion and Next Steps
You don’t need a cluster to get value from AI. With Python, scikit-learn, and statsmodels on Linux, you can build useful, automatable solutions that run right from Bash:
Predictive maintenance for operations
NLP triage to speed up support
Time-series forecasts for planning
Anomaly detection for observability
Your next step:
Pick one case above and run it end-to-end in your venv.
Swap the synthetic data for your real CSVs/logs.
Measure results, iterate, and then wire it into cron or a CI pipeline.
If you want a deeper dive next, consider:
Adding model versioning and metrics tracking
Packaging scripts as a CLI with argparse and Make
Containerizing with Podman or Docker for deployment
Questions or want a follow-up article on deploying these with systemd or in Kubernetes? Let me know what you’d like to see next.