- Posted on
- • Artificial Intelligence
Artificial Intelligence Python Portfolio Projects
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
Artificial Intelligence Python Portfolio Projects (for Linux + Bash lovers)
Want to turn your terminal into an AI portfolio factory? If you’re comfortable in Bash and curious about AI, you can ship practical, resume-worthy projects in days—not months. The key is to build small, focused tools that run well on Linux, are easy to test with shell pipelines, and are reproducible end-to-end.
This post shows you why that matters and gives you three real projects you can build today, complete with install commands (apt, dnf, zypper), bash-friendly interfaces, and minimal Python code.
Why AI projects on Linux are a great bet
Signal > buzzwords: Recruiters want proof you can ship. Small but real tools beat vague claims every time.
Reproducibility: Linux + Bash + Python virtual environments make it trivial to script, automate, and containerize.
Glue power: You can chain your models with grep/sed/jq, cron, systemd, and curl for real-world automation.
Quick setup (Debian/Ubuntu, Fedora/RHEL, openSUSE)
You’ll need Python, build tools, and Git. Pick your package manager:
- Debian/Ubuntu (apt):
sudo apt update
sudo apt install -y python3 python3-venv python3-pip build-essential git curl
- Fedora/RHEL (dnf):
sudo dnf groupinstall -y "Development Tools"
sudo dnf install -y python3 python3-pip git curl
- openSUSE (zypper):
sudo zypper refresh
sudo zypper install -y python3 python3-pip python3-virtualenv gcc gcc-c++ make git curl
Create and activate a Python virtual environment:
python3 -m venv ~/.venvs/ai-portfolio
source ~/.venvs/ai-portfolio/bin/activate
python -m pip install --upgrade pip
Tip (optional, for better Pillow/Image support):
apt:
sudo apt install -y libjpeg-dev zlib1g-devdnf:
sudo dnf install -y libjpeg-turbo-devel zlib-develzypper:
sudo zypper install -y libjpeg8-devel zlib-devel
Project 1: Terminal Sentiment Analyzer (stdin -> sentiment)
A tiny CLI that reads text from stdin or a file and returns positive/negative with confidence. Great demo of NLP + Bash pipelines.
Install Python deps (CPU-only PyTorch + Transformers):
pip install --upgrade "torch>=2.0" torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
pip install transformers
sentiment_cli.py:
#!/usr/bin/env python3
import sys, argparse, json
from transformers import pipeline
def main():
p = argparse.ArgumentParser(description="Classify sentiment from stdin or a file.")
p.add_argument("-f", "--file", help="Path to a text file (one doc or multiple lines).")
p.add_argument("--max", type=int, default=None, help="Limit lines when reading file/stdin.")
args = p.parse_args()
nlp = pipeline("sentiment-analysis") # distilbert-base-uncased-finetuned-sst-2-english
def classify(text):
res = nlp(text)[0]
return {"label": res["label"], "score": float(res["score"]), "text": text.strip()[:200]}
items = []
if args.file:
with open(args.file, "r", encoding="utf-8") as fh:
for i, line in enumerate(fh, 1):
if args.max and i > args.max: break
if line.strip():
items.append(classify(line))
else:
data = sys.stdin.read().strip()
if "\n" in data:
for i, line in enumerate(data.splitlines(), 1):
if args.max and i > args.max: break
if line.strip():
items.append(classify(line))
elif data:
items.append(classify(data))
for obj in items:
print(json.dumps(obj, ensure_ascii=False))
if __name__ == "__main__":
main()
Make it executable and try:
chmod +x sentiment_cli.py
echo "I absolutely love Linux!" | ./sentiment_cli.py | jq
./sentiment_cli.py -f comments.txt --max 10 | jq -r '.label + "\t" + (.score|tostring) + "\t" + .text'
What this shows:
Real NLP with one file.
Unix-friendly JSON output, ready for jq/grep/awk.
Project 2: FastAPI Microservice (Iris classifier)
Turn a simple ML model into a web service you can curl. This demonstrates reproducible training + serving, and integrates well with Docker or systemd.
Install deps:
pip install scikit-learn fastapi "uvicorn[standard]" joblib pydantic
Train and persist a model (RandomForest on Iris):
train_iris.py:
#!/usr/bin/env python3
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import joblib, pathlib
X, y = load_iris(return_X_y=True, as_frame=True)
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.2, random_state=42)
model = RandomForestClassifier(n_estimators=200, random_state=42).fit(Xtr, ytr)
acc = accuracy_score(yte, model.predict(Xte))
print(f"Test accuracy: {acc:.3f}")
pathlib.Path("models").mkdir(exist_ok=True)
joblib.dump(model, "models/iris_rf.joblib")
Serve it with FastAPI:
api.py:
#!/usr/bin/env python3
from fastapi import FastAPI
from pydantic import BaseModel, conlist
import joblib
from sklearn.datasets import load_iris
app = FastAPI(title="Iris Classifier")
model = joblib.load("models/iris_rf.joblib")
target_names = load_iris().target_names.tolist()
class PredictRequest(BaseModel):
features: conlist(float, min_items=4, max_items=4)
@app.post("/predict")
def predict(req: PredictRequest):
pred = model.predict([req.features])[0]
proba = model.predict_proba([req.features])[0].max()
return {"class": target_names[int(pred)], "confidence": float(proba)}
Run and test:
python train_iris.py
uvicorn api:app --reload --host 0.0.0.0 --port 8000
curl -s -X POST http://127.0.0.1:8000/predict \
-H 'Content-Type: application/json' \
-d '{"features":[5.1,3.5,1.4,0.2]}'
What this shows:
Clear separation of train/serve.
Type-checked JSON I/O via Pydantic.
Ready for Docker, Nginx, or systemd.
Project 3: Image Auto-Tagger (ResNet labels from CLI)
Auto-tag images with ImageNet labels. Use it to sort photos or label screenshots; it’s a strong demo of CV with pre-trained models.
Install deps (CPU is fine):
pip install --upgrade "torch>=2.0" torchvision --index-url https://download.pytorch.org/whl/cpu
pip install pillow tqdm
image_tag.py:
#!/usr/bin/env python3
import argparse, json, sys, pathlib
from PIL import Image
import torch
from torchvision import transforms
from torchvision.models import resnet50, ResNet50_Weights
from tqdm import tqdm
def load_model():
weights = ResNet50_Weights.DEFAULT
model = resnet50(weights=weights)
model.eval()
preprocess = weights.transforms()
classes = weights.meta["categories"]
return model, preprocess, classes
@torch.no_grad()
def classify_image(path, model, preprocess, classes, topk=5):
img = Image.open(path).convert("RGB")
x = preprocess(img).unsqueeze(0)
logits = model(x)
probs = torch.nn.functional.softmax(logits, dim=1)[0]
topk_probs, topk_idx = probs.topk(topk)
return [(classes[i], float(p)) for p, i in zip(topk_probs, topk_idx)]
def main():
p = argparse.ArgumentParser(description="Image auto-tagger (ImageNet labels).")
p.add_argument("paths", nargs="+", help="Image files or directories")
p.add_argument("--topk", type=int, default=5)
args = p.parse_args()
model, preprocess, classes = load_model()
files = []
for pth in args.paths:
p = pathlib.Path(pth)
if p.is_file():
files.append(p)
elif p.is_dir():
files += [f for f in p.rglob("*") if f.suffix.lower() in {".jpg",".jpeg",".png",".bmp",".gif"}]
if not files:
print("No images found.", file=sys.stderr); sys.exit(1)
for f in tqdm(files):
try:
tags = classify_image(f, model, preprocess, classes, topk=args.topk)
print(json.dumps({"path": str(f), "tags": tags}, ensure_ascii=False))
except Exception as e:
print(json.dumps({"path": str(f), "error": str(e)}))
if __name__ == "__main__":
main()
Use it from Bash:
chmod +x image_tag.py
./image_tag.py ~/Pictures | jq -r '.path + "\t" + ([.tags[][0]] | join(", "))' | head
find . -type f -name "*.jpg" -print0 | xargs -0 -n1 ./image_tag.py | jq .
What this shows:
Real CV inference without training.
JSON output for storage or post-processing.
Scales to directories via find/xargs.
Bonus: Bash-native practices that make portfolio projects shine
Treat everything as a CLI: stdin/stdout, exit codes,
--help.Emit structured logs: newline-delimited JSON makes jq a superpower.
Reproducibility: include
requirements.txt, a Makefile, and a short README with run commands.Add tests: even a few
pytestcases impress.Automate: a
make serve,make train, andmake testgo a long way.
Example Makefile:
.PHONY: venv install train serve test
venv:
python3 -m venv .venv && . .venv/bin/activate && python -m pip install --upgrade pip
install:
. .venv/bin/activate && pip install -r requirements.txt
train:
. .venv/bin/activate && python train_iris.py
serve:
. .venv/bin/activate && uvicorn api:app --host 0.0.0.0 --port 8000
test:
. .venv/bin/activate && pytest -q
Conclusion / Call To Action
Pick one project and ship it this week:
Sentiment CLI if you like NLP and shell pipelines.
Iris API if you want web-serving and MLOps basics.
Image Tagger if you want quick CV results.
Next steps: 1) Create a repo per project with README, Makefile, and demo commands. 2) Add a short demo GIF or asciinema. 3) Post a write-up linking code, sample data, and curl/pipe examples. 4) Keep iterating: add tests, Dockerfile, and CI later.
Your Linux terminal is already an AI lab. Open a venv, paste one script, and you’ve got portfolio gold.