diff --git a/CHANGELOG.md b/CHANGELOG.md
index e8e3fc9..8b0eb24 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [0.2.0] - 2024-10-14
+
+### Added
+
+- New European model using MobileViTV2 - trained on +40 countries 🚀 .
+- Added more logging to train script.
+
+[0.2.0]: https://github.com/ankandrew/fast-plate-ocr/compare/v0.1.6...v0.2.0
+
## [0.1.6] - 2024-05-09
### Added
diff --git a/README.md b/README.md
index dd607dd..e2a230a 100644
--- a/README.md
+++ b/README.md
@@ -23,6 +23,9 @@ the trained models for inference.
The idea is to use this after a plate object detector, since the OCR expects the cropped plates.
+> [!TIP]
+> Try `fast-plate-ocr` pre-trained models in [Hugging Spaces](https://huggingface.co/spaces/ankandrew/fast-alpr).
+
### Features
- **Keras 3 Backend Support**: Compatible with **[TensorFlow](https://www.tensorflow.org/)**, **[JAX](https://github.com/google/jax)**, and **[PyTorch](https://pytorch.org/)** backends ðŸ§
@@ -40,15 +43,14 @@ The idea is to use this after a plate object detector, since the OCR expects the
| `argentinian-plates-cnn-synth-model` | 2.1 | 476 | [arg_plate_dataset.zip](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/arg_plate_dataset_plus_synth.zip) | 94.19% | Plates up to 2020 + synthetic plates. |
| 🆕 `european-plates-mobile-vit-v2-model` | 2.9 | 344 | - | 92.5%[3] | European plates (+40 countries). |
-> [!TIP]
-> Try `fast-plate-ocr` pre-trained models in [Hugging Spaces](https://huggingface.co/spaces/ankandrew/fast-alpr).
-_[1] Inference on Mac M1 chip using CPUExecutionProvider. Utilizing CoreMLExecutionProvider accelerates speed
+> [!NOTE]
+> _[1] Inference on Mac M1 chip using CPUExecutionProvider. Utilizing CoreMLExecutionProvider accelerates speed
by 5x in the CNN models._
-
-_[2] Accuracy is what we refer as plate_acc. See [metrics section](#model-metrics)._
-
-_[3] For detailed accuracy for each country see [results](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/european_mobile_vit_v2_ocr_results.json) and
+>
+> _[2] Accuracy is what we refer as plate_acc. See [metrics section](#model-metrics)._
+>
+> _[3] For detailed accuracy for each country see [results](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/european_mobile_vit_v2_ocr_results.json) and
the corresponding [val split](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/european_mobile_vit_v2_ocr_val.zip) used._
@@ -136,6 +138,9 @@ To train or use the CLI tool, you'll need to install:
pip install fast_plate_ocr[train]
```
+> [!IMPORTANT]
+> Make sure you have installed a supported backend for Keras.
+
#### Train Model
To train the model you will need:
diff --git a/fast_plate_ocr/cli/train.py b/fast_plate_ocr/cli/train.py
index d986452..d5b8310 100644
--- a/fast_plate_ocr/cli/train.py
+++ b/fast_plate_ocr/cli/train.py
@@ -66,6 +66,13 @@
type=float,
help="Initial learning rate to use.",
)
+@click.option(
+ "--label-smoothing",
+ default=0.05,
+ show_default=True,
+ type=float,
+ help="Amount of label smoothing to apply.",
+)
@click.option(
"--batch-size",
default=128,
@@ -142,6 +149,11 @@
type=click.Choice(["max", "avg"]),
help="Choose the pooling layer to use.",
)
+@click.option(
+ "--weights-path",
+ type=click.Path(exists=True, file_okay=True, path_type=pathlib.Path),
+ help="Path to the pretrained model weights file.",
+)
@print_params(table_title="CLI Training Parameters", c1_title="Parameter", c2_title="Details")
def train(
dense: bool,
@@ -150,6 +162,7 @@ def train(
val_annotations: pathlib.Path,
augmentation_path: pathlib.Path | None,
lr: float,
+ label_smoothing: float,
batch_size: int,
num_workers: int,
output_dir: pathlib.Path,
@@ -161,6 +174,7 @@ def train(
reduce_lr_factor: float,
activation: str,
pool_layer: Literal["max", "avg"],
+ weights_path: pathlib.Path | None,
) -> None:
"""
Train the License Plate OCR model.
@@ -200,8 +214,12 @@ def train(
activation=activation,
pool_layer=pool_layer,
)
+
+ if weights_path:
+ model.load_weights(weights_path)
+
model.compile(
- loss=cce_loss(vocabulary_size=config.vocabulary_size),
+ loss=cce_loss(vocabulary_size=config.vocabulary_size, label_smoothing=label_smoothing),
optimizer=Adam(lr),
metrics=[
cat_acc_metric(
diff --git a/fast_plate_ocr/train/model/custom.py b/fast_plate_ocr/train/model/custom.py
index 9634363..0876379 100644
--- a/fast_plate_ocr/train/model/custom.py
+++ b/fast_plate_ocr/train/model/custom.py
@@ -61,7 +61,7 @@ def top_3_k(y_true, y_pred):
# Custom loss
-def cce_loss(vocabulary_size: int):
+def cce_loss(vocabulary_size: int, label_smoothing: float = 0.2):
"""
Categorical cross-entropy loss.
"""
@@ -73,7 +73,9 @@ def cce(y_true, y_pred):
y_true = ops.reshape(y_true, newshape=(-1, vocabulary_size))
y_pred = ops.reshape(y_pred, newshape=(-1, vocabulary_size))
return ops.mean(
- losses.categorical_crossentropy(y_true, y_pred, from_logits=False, label_smoothing=0.2)
+ losses.categorical_crossentropy(
+ y_true, y_pred, from_logits=False, label_smoothing=label_smoothing
+ )
)
return cce
diff --git a/test/fast_lp_ocr/inference/test_hub.py b/test/fast_lp_ocr/inference/test_hub.py
index 6f86ad6..c55257a 100644
--- a/test/fast_lp_ocr/inference/test_hub.py
+++ b/test/fast_lp_ocr/inference/test_hub.py
@@ -18,7 +18,7 @@ def test_model_and_config_urls(model_name):
model_url, config_url = AVAILABLE_ONNX_MODELS[model_name]
for url in [model_url, config_url]:
- response = requests.get(url, timeout=5, allow_redirects=True)
+ response = requests.head(url, timeout=5, allow_redirects=True)
assert (
response.status_code == HTTPStatus.OK
), f"URL {url} is not accessible, got {response.status_code}"