Msk7000's picture
Upload 6 files
a60082f verified
"""
2015 ๅฎŸ่ฃ…๏ผˆๅ‚็…ง็”จ๏ผ‰โ€” Theano + NumPy ใซใ‚ˆใ‚‹ๆ‰‹ๆ›ธใ CNN
็พๅœจใฎ Theano ใฏ Python 3.12 ไปฅ้™ใงใฏๅ‹•ไฝœใ—ใชใ„ใŸใ‚ใ€
ใ“ใฎใƒ•ใ‚กใ‚คใƒซใฏใ‚ขใƒผใ‚ญใƒ†ใ‚ฏใƒใƒฃ่จ˜้Œฒใƒปๆฏ”่ผƒ็”จ้€”ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใจใ—ใฆไฟๅญ˜ใ™ใ‚‹ใ€‚
ๅฎŸ้š›ใฎๆŽจ่ซ–ใฏ model_2025.py ใง่กŒใ†ใ€‚
"""
# ---------------------------------------------------------------------------
# โ€ป ไปฅไธ‹ใฎใ‚ณใƒผใƒ‰ใฏ Python 3.8 / Theano 1.0 ็’ฐๅขƒใงใฎๅ‹•ไฝœใ‚’ๅ‰ๆใจใ™ใ‚‹
# ---------------------------------------------------------------------------
import numpy as np
try:
import theano
import theano.tensor as T
from theano.tensor.nnet import conv2d
from theano.tensor.signal import pool
THEANO_AVAILABLE = True
except ImportError:
THEANO_AVAILABLE = False
from PIL import Image
import pickle
# ใƒใ‚คใƒ‘ใƒผใƒ‘ใƒฉใƒกใƒผใ‚ฟ
LEARNING_RATE = 0.01
N_EPOCHS = 200
BATCH_SIZE = 50
N_CLASSES = 10
LABELS = [
"airplane", "automobile", "bird", "cat", "deer",
"dog", "frog", "horse", "ship", "truck",
]
MEAN = np.array([0.485, 0.456, 0.406], dtype=np.float32)
STD = np.array([0.229, 0.224, 0.225], dtype=np.float32)
# โ”€โ”€ ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
def _shared_w(shape, name):
return theano.shared(
np.random.normal(0, 0.01, shape).astype(np.float32),
name=name,
)
def _shared_b(n, name):
return theano.shared(np.zeros(n, dtype=np.float32), name=name)
# โ”€โ”€ ใƒขใƒ‡ใƒซๆง‹็ฏ‰ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
def build_model():
if not THEANO_AVAILABLE:
raise RuntimeError(
"Theano ใŒใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใฆใ„ใพใ›ใ‚“ใ€‚"
"Python 3.8 + Theano 1.0 ใฎ็’ฐๅขƒใŒๅฟ…่ฆใงใ™ใ€‚"
)
# ้‡ใฟใƒ‘ใƒฉใƒกใƒผใ‚ฟ
W0 = _shared_w((32, 3, 5, 5), "W0") # Conv 1
b0 = _shared_b(32, "b0")
W1 = _shared_w((64, 32, 5, 5), "W1") # Conv 2
b1 = _shared_b(64, "b1")
W2 = _shared_w((64 * 5 * 5, 512), "W2") # FC 1
b2 = _shared_b(512, "b2")
W3 = _shared_w((512, N_CLASSES), "W3") # ๅ‡บๅŠ›
b3 = _shared_b(N_CLASSES, "b3")
params = [W0, b0, W1, b1, W2, b2, W3, b3]
# ใ‚ทใƒณใƒœใƒซๅค‰ๆ•ฐ
x = T.tensor4("x")
y = T.ivector("y")
# ใƒ•ใ‚ฉใƒฏใƒผใƒ‰ใƒ‘ใ‚น๏ผˆๆ‰‹ๅ‹•ๅฎŸ่ฃ…๏ผ‰
conv0 = T.tanh(
pool.pool_2d(
conv2d(x, W0,
input_shape=(BATCH_SIZE, 3, 32, 32),
filter_shape=(32, 3, 5, 5))
+ b0.dimshuffle("x", 0, "x", "x"),
ws=(2, 2), ignore_border=True,
)
)
conv1 = T.tanh(
pool.pool_2d(
conv2d(conv0, W1, filter_shape=(64, 32, 5, 5))
+ b1.dimshuffle("x", 0, "x", "x"),
ws=(2, 2), ignore_border=True,
)
)
flat = conv1.flatten(2)
fc = T.tanh(T.dot(flat, W2) + b2)
out = T.nnet.softmax(T.dot(fc, W3) + b3)
# ๆๅคฑใƒปๅ‹พ้…ใƒปSGD ๆ›ดๆ–ฐๅ‰‡
loss = -T.mean(T.log(out)[T.arange(y.shape[0]), y])
pred = T.argmax(out, axis=1)
err = T.mean(T.neq(pred, y))
grads = T.grad(loss, params)
updates = [(p, p - LEARNING_RATE * g) for p, g in zip(params, grads)]
# Theano ้–ขๆ•ฐใฎใ‚ณใƒณใƒ‘ใ‚คใƒซ๏ผˆGPUใ‚ฐใƒฉใƒ•ๆœ€้ฉๅŒ–ใŒ่ตฐใ‚‹ใŸใ‚ๆ•ฐๅ็ง’ใ‹ใ‹ใ‚‹๏ผ‰
train_fn = theano.function([x, y], [loss, err], updates=updates)
pred_fn = theano.function([x], pred)
return params, train_fn, pred_fn
# โ”€โ”€ ๅ‰ๅ‡ฆ็† โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
def preprocess(image) -> np.ndarray:
"""PIL.Image ใพใŸใฏ ใƒ‘ใ‚นใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€(1, 3, 32, 32) ใฎ float32 ้…ๅˆ—ใ‚’่ฟ”ใ™ใ€‚"""
if isinstance(image, str):
image = Image.open(image)
img = image.convert("RGB").resize((32, 32))
arr = np.array(img, dtype=np.float32) / 255.0
arr = (arr - MEAN) / STD # ใƒใƒฃใƒณใƒใƒซใ”ใจใฎๆญฃ่ฆๅŒ–
arr = arr.transpose(2, 0, 1) # HWC โ†’ CHW
return arr[np.newaxis] # ใƒใƒƒใƒๆฌกๅ…ƒใ‚’่ฟฝๅŠ 
# โ”€โ”€ ๅญฆ็ฟ’ใƒซใƒผใƒ— โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
def fit(train_fn, X_train: np.ndarray, y_train: np.ndarray) -> None:
n = len(X_train)
for epoch in range(N_EPOCHS):
idx = np.random.permutation(n)
losses, errs = [], []
for i in range(n // BATCH_SIZE):
b = idx[i * BATCH_SIZE : (i + 1) * BATCH_SIZE]
l, e = train_fn(X_train[b], y_train[b])
losses.append(l)
errs.append(e)
print(
f"Epoch {epoch + 1:3d} / {N_EPOCHS} "
f"loss={np.mean(losses):.4f} "
f"err={np.mean(errs):.4f}"
)
# โ”€โ”€ ๆŽจ่ซ– โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
def classify(pred_fn, image) -> str:
arr = preprocess(image)
idx = pred_fn(arr)[0]
return LABELS[idx]
# โ”€โ”€ ใƒขใƒ‡ใƒซใฎไฟๅญ˜ / ่ชญใฟ่พผใฟ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
def save_model(params, path: str) -> None:
weights = [p.get_value() for p in params]
with open(path, "wb") as f:
pickle.dump(weights, f, protocol=2)
def load_model(params, path: str) -> None:
with open(path, "rb") as f:
weights = pickle.load(f)
for p, w in zip(params, weights):
p.set_value(w)