hướng dẫn chạy với google colab
This commit is contained in:
@@ -0,0 +1,445 @@
|
|||||||
|
# Demo Website trên Google Colab với FRP
|
||||||
|
|
||||||
|
Hướng dẫn này giúp bạn chạy toàn bộ hệ thống **remote-sensing** trên Google Colab
|
||||||
|
và expose ra internet qua **FRP (Fast Reverse Proxy)** — không cần ngrok, URL cố định, không giới hạn session.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Yêu cầu
|
||||||
|
|
||||||
|
| Thành phần | Mô tả |
|
||||||
|
|---|---|
|
||||||
|
| **Google Colab** | Tài khoản Google thông thường (free tier là đủ) |
|
||||||
|
| **Google Drive** | Dùng để lưu project và models |
|
||||||
|
| **1 VPS có IP public** | Chạy `frps` server — VPS $3–5/tháng là đủ |
|
||||||
|
| **Port mở trên VPS** | 7000 (FRP control) + 8080 (web traffic) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phần 1 — Chuẩn bị VPS (chạy 1 lần, giữ mãi)
|
||||||
|
|
||||||
|
### Bước 1.1 — Download FRP lên VPS
|
||||||
|
|
||||||
|
SSH vào VPS rồi chạy:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget https://github.com/fatedier/frp/releases/download/v0.61.1/frp_0.61.1_linux_amd64.tar.gz
|
||||||
|
tar -xzf frp_0.61.1_linux_amd64.tar.gz
|
||||||
|
cd frp_0.61.1_linux_amd64
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bước 1.2 — Tạo file cấu hình `frps.toml`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat > frps.toml << 'EOF'
|
||||||
|
bindPort = 7000
|
||||||
|
auth.token = "your_secret_token_here"
|
||||||
|
|
||||||
|
# Dashboard để theo dõi kết nối (tuỳ chọn)
|
||||||
|
webServer.port = 7500
|
||||||
|
webServer.user = "admin"
|
||||||
|
webServer.password = "admin123"
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠️ Đặt `auth.token` thành chuỗi bí mật của bạn, ví dụ: `"rs_demo_2026_abc123"`. Phải giống với phía Colab.
|
||||||
|
|
||||||
|
### Bước 1.3 — Chạy frps
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test chạy foreground (Ctrl+C để dừng)
|
||||||
|
./frps -c frps.toml
|
||||||
|
|
||||||
|
# Chạy nền (production)
|
||||||
|
nohup ./frps -c frps.toml > frps.log 2>&1 &
|
||||||
|
|
||||||
|
# Kiểm tra đang chạy
|
||||||
|
ps aux | grep frps
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bước 1.4 — Mở firewall VPS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ubuntu/Debian
|
||||||
|
ufw allow 7000 # FRP control port
|
||||||
|
ufw allow 8080 # Web traffic port
|
||||||
|
ufw allow 7500 # Dashboard (tuỳ chọn)
|
||||||
|
ufw reload
|
||||||
|
|
||||||
|
# CentOS/RHEL
|
||||||
|
firewall-cmd --permanent --add-port=7000/tcp
|
||||||
|
firewall-cmd --permanent --add-port=8080/tcp
|
||||||
|
firewall-cmd --reload
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bước 1.5 — Kiểm tra frps hoạt động
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Xem log
|
||||||
|
tail -f frps.log
|
||||||
|
|
||||||
|
# Kết quả kỳ vọng:
|
||||||
|
# [frps] frp service started, listen on 0.0.0.0:7000
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phần 2 — Chuẩn bị Google Drive
|
||||||
|
|
||||||
|
### Bước 2.1 — Upload project lên Drive
|
||||||
|
|
||||||
|
Cấu trúc thư mục trên Google Drive:
|
||||||
|
|
||||||
|
```
|
||||||
|
My Drive/
|
||||||
|
└── remote-sensing/
|
||||||
|
├── api_server.py
|
||||||
|
├── train_module.py
|
||||||
|
├── feature_extractor.py
|
||||||
|
├── model_manager.py
|
||||||
|
├── cloud_removal.py
|
||||||
|
├── report_generator.py
|
||||||
|
├── generate_previews.py
|
||||||
|
├── vietnam_provinces.py
|
||||||
|
├── vietnam_provinces_merged.py
|
||||||
|
├── utils.py
|
||||||
|
├── model_train/ ← copy toàn bộ models đã train
|
||||||
|
│ ├── *.joblib
|
||||||
|
│ └── *.json
|
||||||
|
├── cloud_removal_model/ ← copy nếu dùng cloud removal DL
|
||||||
|
│ └── *.pth
|
||||||
|
├── predictions/ ← để trống, Colab sẽ tạo output vào đây
|
||||||
|
├── reports/ ← để trống
|
||||||
|
└── training_interface.html ← và tất cả *.html
|
||||||
|
```
|
||||||
|
|
||||||
|
> 💡 Upload nhanh nhất: zip toàn bộ folder `remote-sensing`, upload 1 file zip lên Drive, rồi giải nén bằng Colab.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phần 3 — Notebook Google Colab
|
||||||
|
|
||||||
|
Tạo notebook mới tại [colab.google.com](https://colab.google.com) và paste từng cell sau.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Cell 1 — Mount Drive và di chuyển vào project
|
||||||
|
|
||||||
|
```python
|
||||||
|
from google.colab import drive
|
||||||
|
drive.mount('/content/drive')
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
PROJECT_PATH = '/content/drive/MyDrive/remote-sensing'
|
||||||
|
os.chdir(PROJECT_PATH)
|
||||||
|
|
||||||
|
print(f"Working directory: {os.getcwd()}")
|
||||||
|
print("Files:", os.listdir()[:10])
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Cell 2 — Giải nén nếu upload dạng zip (tuỳ chọn)
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Chỉ chạy nếu bạn upload file zip
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
ZIP_PATH = '/content/drive/MyDrive/remote-sensing.zip'
|
||||||
|
EXTRACT_TO = '/content/drive/MyDrive/'
|
||||||
|
|
||||||
|
if os.path.exists(ZIP_PATH):
|
||||||
|
with zipfile.ZipFile(ZIP_PATH, 'r') as z:
|
||||||
|
z.extractall(EXTRACT_TO)
|
||||||
|
print("✅ Extracted successfully")
|
||||||
|
else:
|
||||||
|
print("⏭️ No zip found, skipping")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Cell 3 — Cài dependencies (chạy lần đầu, ~8–12 phút)
|
||||||
|
|
||||||
|
```python
|
||||||
|
print("Installing core API dependencies...")
|
||||||
|
!pip install -q fastapi uvicorn pydantic
|
||||||
|
|
||||||
|
print("Installing geospatial + ML dependencies...")
|
||||||
|
!pip install -q \
|
||||||
|
numpy pandas xarray rasterio rioxarray geopandas shapely \
|
||||||
|
scikit-learn xgboost joblib \
|
||||||
|
matplotlib pillow markdown
|
||||||
|
|
||||||
|
print("Installing Planetary Computer dependencies...")
|
||||||
|
!pip install -q pystac-client planetary-computer odc-stac
|
||||||
|
|
||||||
|
print("Installing PyTorch (GPU)...")
|
||||||
|
!pip install -q torch torchvision \
|
||||||
|
--extra-index-url https://download.pytorch.org/whl/cu118
|
||||||
|
|
||||||
|
print("✅ All dependencies installed")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Cell 4 — Kiểm tra GPU và môi trường
|
||||||
|
|
||||||
|
```python
|
||||||
|
import torch
|
||||||
|
|
||||||
|
print(f"PyTorch version : {torch.__version__}")
|
||||||
|
print(f"GPU available : {torch.cuda.is_available()}")
|
||||||
|
if torch.cuda.is_available():
|
||||||
|
print(f"GPU name : {torch.cuda.get_device_name(0)}")
|
||||||
|
|
||||||
|
import rasterio, xarray, geopandas
|
||||||
|
print(f"rasterio : {rasterio.__version__}")
|
||||||
|
print(f"xarray : {xarray.__version__}")
|
||||||
|
print(f"geopandas : {geopandas.__version__}")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Cell 5 — Download và cấu hình frpc
|
||||||
|
|
||||||
|
```python
|
||||||
|
import subprocess, os
|
||||||
|
|
||||||
|
# Download frpc
|
||||||
|
!wget -q https://github.com/fatedier/frp/releases/download/v0.61.1/frp_0.61.1_linux_amd64.tar.gz \
|
||||||
|
-O /tmp/frp.tar.gz
|
||||||
|
!tar -xzf /tmp/frp.tar.gz -C /tmp/
|
||||||
|
!chmod +x /tmp/frp_0.61.1_linux_amd64/frpc
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# ⚠️ SỬA 2 DÒNG NÀY TRƯỚC KHI CHẠY
|
||||||
|
VPS_IP = "123.456.789.000" # IP public của VPS bạn
|
||||||
|
FRP_TOKEN = "your_secret_token_here" # Phải giống frps.toml trên VPS
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
frpc_config = f"""
|
||||||
|
serverAddr = "{VPS_IP}"
|
||||||
|
serverPort = 7000
|
||||||
|
auth.token = "{FRP_TOKEN}"
|
||||||
|
|
||||||
|
[[proxies]]
|
||||||
|
name = "remote-sensing-web"
|
||||||
|
type = "tcp"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 8000
|
||||||
|
remotePort = 8080
|
||||||
|
"""
|
||||||
|
|
||||||
|
with open('/tmp/frpc.toml', 'w') as f:
|
||||||
|
f.write(frpc_config)
|
||||||
|
|
||||||
|
print(f"✅ frpc configured → VPS: {VPS_IP}:8080")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Cell 6 — Khởi động FastAPI server
|
||||||
|
|
||||||
|
```python
|
||||||
|
import subprocess, time, os
|
||||||
|
|
||||||
|
os.chdir('/content/drive/MyDrive/remote-sensing')
|
||||||
|
|
||||||
|
# Khởi động FastAPI
|
||||||
|
server = subprocess.Popen(
|
||||||
|
["uvicorn", "api_server:app",
|
||||||
|
"--host", "127.0.0.1",
|
||||||
|
"--port", "8000",
|
||||||
|
"--log-level", "warning"],
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE
|
||||||
|
)
|
||||||
|
|
||||||
|
time.sleep(4)
|
||||||
|
|
||||||
|
# Kiểm tra server đã lên chưa
|
||||||
|
if server.poll() is None:
|
||||||
|
print("✅ FastAPI server is running on port 8000")
|
||||||
|
else:
|
||||||
|
out, err = server.communicate()
|
||||||
|
print("❌ Server failed to start:")
|
||||||
|
print(err.decode()[:1000])
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Cell 7 — Khởi động frpc tunnel
|
||||||
|
|
||||||
|
```python
|
||||||
|
import subprocess, time
|
||||||
|
|
||||||
|
frpc = subprocess.Popen(
|
||||||
|
["/tmp/frp_0.61.1_linux_amd64/frpc", "-c", "/tmp/frpc.toml"],
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE
|
||||||
|
)
|
||||||
|
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
if frpc.poll() is None:
|
||||||
|
print("✅ FRP tunnel is active")
|
||||||
|
print("=" * 55)
|
||||||
|
print(f"🌐 Main site : http://{VPS_IP}:8080")
|
||||||
|
print(f"📊 Dashboard : http://{VPS_IP}:8080/dashboard")
|
||||||
|
print(f"🏋️ Training : http://{VPS_IP}:8080/training")
|
||||||
|
print(f"🔮 Prediction : http://{VPS_IP}:8080/prediction")
|
||||||
|
print(f"📦 Batch : http://{VPS_IP}:8080/batch")
|
||||||
|
print(f"🌿 NDVI : http://{VPS_IP}:8080/ndvi")
|
||||||
|
print(f"📈 Reports : http://{VPS_IP}:8080/reports")
|
||||||
|
print("=" * 55)
|
||||||
|
else:
|
||||||
|
out, err = frpc.communicate()
|
||||||
|
print("❌ FRP failed:")
|
||||||
|
print(err.decode()[:500])
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Cell 8 — Kiểm tra toàn bộ hệ thống
|
||||||
|
|
||||||
|
```python
|
||||||
|
import urllib.request, json
|
||||||
|
|
||||||
|
BASE = "http://127.0.0.1:8000"
|
||||||
|
checks = [
|
||||||
|
("/api/network/check", "Network connectivity"),
|
||||||
|
("/api/models/list", "Model list"),
|
||||||
|
("/api/provinces/list", "Province list"),
|
||||||
|
("/api/cloud-removal/methods", "Cloud removal methods"),
|
||||||
|
]
|
||||||
|
|
||||||
|
for path, label in checks:
|
||||||
|
try:
|
||||||
|
r = urllib.request.urlopen(BASE + path, timeout=5)
|
||||||
|
data = json.loads(r.read())
|
||||||
|
status = "✅"
|
||||||
|
except Exception as e:
|
||||||
|
data = str(e)
|
||||||
|
status = "❌"
|
||||||
|
print(f"{status} {label:<30} → {str(data)[:80]}")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Cell 9 — Xem log nếu có lỗi (tuỳ chọn)
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Xem stderr của FastAPI
|
||||||
|
import select, sys
|
||||||
|
|
||||||
|
if server.poll() is not None:
|
||||||
|
_, err = server.communicate()
|
||||||
|
print("FastAPI stderr:")
|
||||||
|
print(err.decode())
|
||||||
|
else:
|
||||||
|
# Đọc log không block
|
||||||
|
import os
|
||||||
|
flags = os.O_RDONLY | os.O_NONBLOCK
|
||||||
|
try:
|
||||||
|
fd = server.stderr.fileno()
|
||||||
|
os.set_blocking(fd, False)
|
||||||
|
print(server.stderr.read(2000).decode())
|
||||||
|
except:
|
||||||
|
print("Server is running (no errors captured)")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Cell 10 — Dừng server khi xong demo
|
||||||
|
|
||||||
|
```python
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
server.terminate()
|
||||||
|
frpc.terminate()
|
||||||
|
|
||||||
|
print("✅ FastAPI stopped")
|
||||||
|
print("✅ FRP tunnel closed")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phần 4 — Dùng domain thay vì IP (nâng cao)
|
||||||
|
|
||||||
|
Nếu VPS có domain riêng, bạn có thể truy cập bằng URL đẹp hơn.
|
||||||
|
|
||||||
|
### Sửa `frps.toml` trên VPS
|
||||||
|
|
||||||
|
```toml
|
||||||
|
bindPort = 7000
|
||||||
|
auth.token = "your_secret_token_here"
|
||||||
|
vhostHTTPPort = 80
|
||||||
|
```
|
||||||
|
|
||||||
|
### Sửa Cell 5 (`frpc.toml`) trên Colab
|
||||||
|
|
||||||
|
```toml
|
||||||
|
serverAddr = "your-vps.com"
|
||||||
|
serverPort = 7000
|
||||||
|
auth.token = "your_secret_token_here"
|
||||||
|
|
||||||
|
[[proxies]]
|
||||||
|
name = "remote-sensing-web"
|
||||||
|
type = "http"
|
||||||
|
localPort = 8000
|
||||||
|
customDomains = ["demo.your-vps.com"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### DNS — trỏ subdomain về VPS
|
||||||
|
|
||||||
|
```
|
||||||
|
demo.your-vps.com → A record → 123.456.789.000
|
||||||
|
```
|
||||||
|
|
||||||
|
→ Truy cập: `http://demo.your-vps.com` (không cần `:8080`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phần 5 — Giữ session Colab sống lâu hơn
|
||||||
|
|
||||||
|
Colab tự disconnect sau ~90 phút idle. Để tránh:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Paste vào console trình duyệt (F12 → Console)
|
||||||
|
function keepAlive() {
|
||||||
|
document.querySelector('#connect button')?.click();
|
||||||
|
console.log('keep-alive ping:', new Date().toLocaleTimeString());
|
||||||
|
}
|
||||||
|
setInterval(keepAlive, 60000);
|
||||||
|
```
|
||||||
|
|
||||||
|
Hoặc dùng **Colab Pro** ($10/tháng) để không bị giới hạn session.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phần 6 — Tóm tắt so sánh FRP vs ngrok
|
||||||
|
|
||||||
|
| Tiêu chí | FRP (self-host) | ngrok (free) |
|
||||||
|
|---|---|---|
|
||||||
|
| URL cố định | ✅ Có | ❌ Đổi mỗi session |
|
||||||
|
| Session timeout | ✅ Không giới hạn | ⚠️ 2 giờ |
|
||||||
|
| Chi phí | Free (cần VPS) | Free tier có giới hạn |
|
||||||
|
| Dữ liệu qua server bên thứ 3 | ❌ Không | ✅ Qua server ngrok |
|
||||||
|
| Cần setup | ⚠️ Cần cài frps trên VPS | ✅ Chạy ngay |
|
||||||
|
| Phù hợp | Demo dài hạn, production | Demo nhanh 1 lần |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Checklist trước khi demo
|
||||||
|
|
||||||
|
- [ ] VPS đang chạy `frps` và port 7000, 8080 đã mở
|
||||||
|
- [ ] Project đã upload đầy đủ lên Google Drive (kể cả `model_train/`)
|
||||||
|
- [ ] Đã điền đúng `VPS_IP` và `FRP_TOKEN` trong Cell 5
|
||||||
|
- [ ] Cell 3 (cài deps) đã chạy thành công
|
||||||
|
- [ ] Cell 8 (health check) cho thấy tất cả ✅
|
||||||
|
- [ ] Truy cập `http://VPS_IP:8080/dashboard` từ trình duyệt → hiện trang
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Tạo ngày: 03/04/2026 — dự án remote-sensing Vietnam Land Classification*
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"filename": "CRGAN_generator.pth",
|
||||||
|
"epoch": 0,
|
||||||
|
"train_loss": 0.0,
|
||||||
|
"val_loss": 0.0,
|
||||||
|
"in_channels": 6,
|
||||||
|
"out_channels": 4,
|
||||||
|
"use_s1": true,
|
||||||
|
"description": "",
|
||||||
|
"uploaded_at": "2026-01-26T13:36:58.433105"
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"filename": "GLFCR_generator.pth",
|
||||||
|
"epoch": 10,
|
||||||
|
"train_loss": 0.014,
|
||||||
|
"val_loss": 0.01,
|
||||||
|
"in_channels": 6,
|
||||||
|
"out_channels": 4,
|
||||||
|
"use_s1": true,
|
||||||
|
"description": "No describe",
|
||||||
|
"uploaded_at": "2026-01-27T10:38:28.134503"
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"filename": "SpAGAN_generator.pth",
|
||||||
|
"epoch": 30,
|
||||||
|
"train_loss": 0.222,
|
||||||
|
"val_loss": 0.11,
|
||||||
|
"in_channels": 6,
|
||||||
|
"out_channels": 4,
|
||||||
|
"use_s1": true,
|
||||||
|
"description": "No data",
|
||||||
|
"uploaded_at": "2026-01-26T13:43:06.751319"
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user