File size: 6,027 Bytes
a60082f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | """
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)
|