<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Darya Petrashka</title>
    <description>The latest articles on DEV Community by Darya Petrashka (@dashapetr).</description>
    <link>https://dev.to/dashapetr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F992960%2Fe4b3f42d-5734-44b6-9d95-6574be0676ed.jpg</url>
      <title>DEV Community: Darya Petrashka</title>
      <link>https://dev.to/dashapetr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dashapetr"/>
    <language>en</language>
    <item>
      <title>[Part 2] Your first steps in Computer Vision on AWS: training a custom CNN model</title>
      <dc:creator>Darya Petrashka</dc:creator>
      <pubDate>Fri, 30 Oct 2026 18:03:21 +0000</pubDate>
      <link>https://dev.to/dashapetr/part-2-your-first-steps-in-computer-vision-on-aws-training-a-custom-cnn-model-1bjm</link>
      <guid>https://dev.to/dashapetr/part-2-your-first-steps-in-computer-vision-on-aws-training-a-custom-cnn-model-1bjm</guid>
      <description>&lt;p&gt;This is the second part of the series "Your first steps in Computer Vision on AWS". If you are just starting, this tutorial will guide you step by step from the initial dataset to a deployed app.&lt;/p&gt;

&lt;p&gt;You can read &lt;a href="https://dev.to/dashapetr/part-1-your-first-steps-in-computer-vision-on-aws-asl-dataset-preprocessing-4h5p"&gt;the first part on ASL dataset + preprocessing&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why training on CPU would take ages
&lt;/h2&gt;

&lt;p&gt;While we used a simple CPU SageMaker notebook instance to work with the data, for training we would need a GPU-powered instance.&lt;br&gt;
A CPU is designed for complex sequential tasks. Training a CNN requires performing millions of simple matrix multiplications and convolutions simultaneously. &lt;br&gt;
A GPU contains thousands of smaller, simpler cores designed to execute thousands of calculations at the exact same time, offering massive parallelism.&lt;/p&gt;

&lt;p&gt;As an analogy, you can picture a &lt;strong&gt;CPU&lt;/strong&gt; as a powerful supercomputer which can perform most complex calculations (and it will &lt;a href="https://simple.wikipedia.org/wiki/42_(answer)" rel="noopener noreferrer"&gt;answer '42'&lt;/a&gt; 😂). A &lt;strong&gt;GPU&lt;/strong&gt; in this case would be a fleet of calculators, each performing simple parallel operations.&lt;/p&gt;

&lt;p&gt;As you can see on the screenshot, one epoch can take 1.5 hours (while we would need 20-25 epochs):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw5kk1fko9l0vz6jbrin5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw5kk1fko9l0vz6jbrin5.png" alt="Training on CPU would take a while" width="796" height="65"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📖 An &lt;strong&gt;epoch&lt;/strong&gt; in machine learning is one complete pass of the entire training dataset through a model.&lt;/p&gt;
&lt;h2&gt;
  
  
  Let's create a GPU-powered SageMaker notebook instance
&lt;/h2&gt;

&lt;p&gt;Let's &lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/howitworks-create-ws.html" rel="noopener noreferrer"&gt;create a SageMaker notebook instance&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The AWS &lt;code&gt;ml.g5.xlarge&lt;/code&gt; SageMaker instance (and the corresponding EC2 &lt;code&gt;g5.xlarge&lt;/code&gt; instance) has 1 NVIDIA A10G Tensor Core GPU with 24 GiB of VRAM (video memory).&lt;/p&gt;

&lt;p&gt;Pricing: &lt;code&gt;ml.g5.xlarge&lt;/code&gt; is not as cheap as &lt;code&gt;ml.t3.medium&lt;/code&gt;. The exact price can vary depending on the region (e.g., for Frankfurt it is $1.258 per hour); see &lt;a href="https://aws.amazon.com/ec2/pricing/on-demand/" rel="noopener noreferrer"&gt;this page for on-demand pricing reference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Don't forget to stop and terminate your instance once the data is processed and uploaded to S3.&lt;/strong&gt; &lt;/p&gt;
&lt;h2&gt;
  
  
  Why CNN model?
&lt;/h2&gt;

&lt;p&gt;Before we get into model training, let's stop for a moment to discuss what a CNN model is and why we selected it.&lt;/p&gt;

&lt;p&gt;📖 A &lt;strong&gt;Convolutional Neural Network (CNN)&lt;/strong&gt; is designed specifically to process and understand visual data. In simple terms, it uses filters/kernels to look at small pieces of the image, detecting simple shapes like edges or lines. Then, it uses pooling to reduce the image size while retaining the most useful information. Simple shapes are combined into more complex features like wheels, eyes, etc. Finally, the model decides what the picture is ("car", "person", etc.).&lt;/p&gt;

&lt;p&gt;Using a CNN for image classification is a good starting point: the model is lightweight (compared to &lt;a href="https://arxiv.org/abs/2107.14062" rel="noopener noreferrer"&gt;fully connected neural networks&lt;/a&gt;), but still quite performant.&lt;/p&gt;

&lt;p&gt;We use different types of layers, stacked together, to build the CNN architecture. As the &lt;strong&gt;input&lt;/strong&gt;, each image has a resolution of 200×200 pixels: raw and filtered RGB images will have 3 channels (200, 200, 3), edge images will have 1 channel (200, 200, 1).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Convolutional Layer&lt;/strong&gt;: applies small, learnable filter matrices (kernels) across input data to extract local visual patterns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pooling&lt;/strong&gt;: each 2×2 &lt;a href="https://en.wikipedia.org/wiki/Pooling_layer" rel="noopener noreferrer"&gt;pooling layer&lt;/a&gt; reduces the image size, e.g. 200 → 100.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Global Average Pooling&lt;/strong&gt;: converts the final 25×25×128 feature maps into 128 values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dense layer&lt;/strong&gt;: 128 neurons combine the extracted features to make the final decision.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dropout&lt;/strong&gt;: randomly turns off 50% of the dense-layer neurons to prevent &lt;a href="https://en.wikipedia.org/wiki/Overfitting" rel="noopener noreferrer"&gt;overfitting&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, the &lt;strong&gt;output&lt;/strong&gt;, where 29 neurons will represent the 29 classes. &lt;a href="https://en.wikipedia.org/wiki/Softmax_function" rel="noopener noreferrer"&gt;Softmax&lt;/a&gt; converts their outputs into probabilities, and the class with the highest probability is the prediction.&lt;/p&gt;

&lt;p&gt;Let's show the model architecture: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj6gtatky76kot8bl4phy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj6gtatky76kot8bl4phy.png" alt="The model architecture" width="606" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our model, the first convolutional layer learns simple features (e.g., edges); the second learns combinations of those features (e.g., finger shapes), while the third learns more complex hand/sign patterns. The number of filters increases (32 → 64 → 128), so the network can learn more types of features.&lt;/p&gt;

&lt;p&gt;You can also see that the model will have 113,501 parameters, whose values will change during training. &lt;/p&gt;

&lt;p&gt;📖 A &lt;strong&gt;parameter&lt;/strong&gt; in a CNN is an internal, learnable variable (specifically, weights and biases) that the model automatically adjusts and optimizes during training through backpropagation.&lt;/p&gt;
&lt;h2&gt;
  
  
  Copy the image data to the instance
&lt;/h2&gt;

&lt;p&gt;Once the SageMaker notebook instance is ready, you can &lt;strong&gt;Open Jupyter / Open JupyterLab&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Upload the &lt;code&gt;Raw_images_training.ipynb&lt;/code&gt; Jupyter notebook &lt;a href="https://github.com/dashapetr/Computer_Vision_ASL_AWS/blob/main/sagemaker_notebooks/Raw_images_training.ipynb" rel="noopener noreferrer"&gt;from the GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Run cell by cell.&lt;/p&gt;

&lt;p&gt;A useful command to use before any training starts: &lt;code&gt;!nvidia-smi&lt;/code&gt;. It would show attached GPUs, temperatures, memory usage, power, and active processes. For example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxggt53rnwdr073okqszc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxggt53rnwdr073okqszc.png" alt="NVIDIA-smi command output" width="674" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⚠️ Don't forget to replace the placeholder and put your S3 bucket name:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;BUCKET = "YOUR_BUCKET"&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;This cell copies the preprocessed data from S3 to the instance. You only need to run it once and then check that the data has been copied successfully.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;!aws s3 sync s3://YOUR-BUCKET/raw/asl_alphabet_train/ /home/ec2-user/SageMaker/asl_alphabet_train/ --quiet
!aws s3 sync s3://YOUR-BUCKET/processed/ /home/ec2-user/SageMaker/asl_preprocessed/  --quiet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Let's train 3 CNN models
&lt;/h2&gt;

&lt;p&gt;⚠️ Remember we had 3 versions of data: raw, Gaussian-filtered and Canny edge? Well, you can use &lt;a href="https://github.com/dashapetr/Computer_Vision_ASL_AWS/blob/main/sagemaker_notebooks/Gaussian_filtered_training.ipynb" rel="noopener noreferrer"&gt;this &lt;code&gt;Gaussian_filtered_training.ipynb&lt;/code&gt; notebook&lt;/a&gt; to train the CNN with Gaussian-filtered images; and &lt;a href="https://github.com/dashapetr/Computer_Vision_ASL_AWS/blob/main/sagemaker_notebooks/Canny_edges_training.ipynb" rel="noopener noreferrer"&gt;this &lt;code&gt;Canny_edges_training.ipynb&lt;/code&gt; notebook&lt;/a&gt; to train the CNN with Canny edge images.&lt;br&gt;
They don't differ much. I created three separate notebooks mainly to keep the cell output histories separate. If for you it is more comfortable to use a single notebook, feel free to do it. The only thing you would need to change is the &lt;code&gt;REPRESENTATION&lt;/code&gt; variable. Set it to &lt;code&gt;raw&lt;/code&gt;, &lt;code&gt;filtered&lt;/code&gt;, or &lt;code&gt;edges&lt;/code&gt; depending on the image version. &lt;/p&gt;

&lt;p&gt;In a nutshell, training the CNN model follows this process:&lt;br&gt;
&lt;strong&gt;image → prediction → compare with correct answer → calculate error → adjust weights → repeat&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  What each notebook does (high-level):
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Creates train/validation/test dataframes&lt;/li&gt;
&lt;li&gt;Designs and compiles the CNN&lt;/li&gt;
&lt;li&gt;Trains the CNN from scratch&lt;/li&gt;
&lt;li&gt;Evaluates on the held-out test set&lt;/li&gt;
&lt;li&gt;Saves the model and uploads it to S3&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Train/validation/test dataframes
&lt;/h3&gt;

&lt;p&gt;⚠️ Note: In some sources, the final held-out dataset is called &lt;em&gt;'validation'&lt;/em&gt;. &lt;br&gt;
Here, we use the &lt;strong&gt;validation&lt;/strong&gt; set to evaluate model performance after each epoch.&lt;br&gt;
The final held-out dataset is called &lt;strong&gt;'test'&lt;/strong&gt; (we will do the final metric evaluation against it).&lt;/p&gt;

&lt;p&gt;We created and recorded the dataset split in the previous part. We saved it in a CSV file, which we now use to retrieve the corresponding image paths.&lt;/p&gt;
&lt;h3&gt;
  
  
  Compile the network
&lt;/h3&gt;

&lt;p&gt;We compile the designed CNN &lt;code&gt;model&lt;/code&gt; using this code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model.compile(
    optimizer=tf.keras.optimizers.Adam(
        learning_rate=0.001
    ),
    loss=tf.keras.losses.SparseCategoricalCrossentropy(),
    metrics=[
        tf.keras.metrics.SparseCategoricalAccuracy(
            name="accuracy"
        )
    ]
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://machinelearningmastery.com/adam-optimization-algorithm-for-deep-learning/" rel="noopener noreferrer"&gt;Adam optimizer&lt;/a&gt; is a popular optimization algorithm used to train deep learning models. &lt;a href="https://www.tensorflow.org/api_docs/python/tf/keras/losses/SparseCategoricalCrossentropy" rel="noopener noreferrer"&gt;SparseCategoricalCrossentropy&lt;/a&gt; is a loss function used for multi-class classification problems where the true labels are provided as integers. Finally, for the metric, we are using &lt;a href="https://www.tensorflow.org/api_docs/python/tf/keras/metrics/SparseCategoricalAccuracy" rel="noopener noreferrer"&gt;SparseCategoricalAccuracy&lt;/a&gt;, an evaluation metric used in multi-class classification models to measure how often model predictions match integer-encoded target labels.&lt;/p&gt;

&lt;p&gt;📖 A &lt;strong&gt;loss function&lt;/strong&gt; in deep learning is a mathematical formula that measures the difference between what a neural network predicts and the actual ground truth label.&lt;/p&gt;

&lt;h2&gt;
  
  
  Model training
&lt;/h2&gt;

&lt;p&gt;We train the model for 25 &lt;code&gt;EPOCHS&lt;/code&gt;. It would take only several minutes to fully train the CNN:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;history = model.fit(
    train_ds,
    validation_data=val_ds,
    epochs=EPOCHS,
    callbacks=callbacks,
    verbose=1
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will save both &lt;strong&gt;best model&lt;/strong&gt; and &lt;strong&gt;final model&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;❓ &lt;em&gt;Why isn't the final model always the best model?&lt;/em&gt; &lt;br&gt;
The final model represents the state of your model's weights after the last training epoch has finished. The best model is the state of your model weights from the epoch that achieved the optimal score (lowest validation loss or highest validation accuracy) during training. For saving the best model, we are using &lt;code&gt;ModelCheckpoint&lt;/code&gt; with &lt;code&gt;save_best_only=True&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once training is finished, it is useful to plot how was the accuracy changes across training epochs. It was increasing, which is a good sign.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fviex1hgq6hhmgqv38bxk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fviex1hgq6hhmgqv38bxk.png" alt="accuracy plot" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The same goes for the loss. It was decreasing, which indicates that the model's predictions were becoming more accurate according to the loss function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq7bjlwuq8swqwbs9wihw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq7bjlwuq8swqwbs9wihw.png" alt="loss plot" width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Model evaluation
&lt;/h3&gt;

&lt;p&gt;We are evaluating the &lt;strong&gt;best&lt;/strong&gt; model on the held-out &lt;strong&gt;test&lt;/strong&gt; dataset with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test_loss, test_accuracy = model.evaluate(
    test_ds,
    verbose=1
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The evaluation results on the test dataset are very good, with an accuracy of 99.34%:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4nm7tpdiqpztzs3hjs5v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4nm7tpdiqpztzs3hjs5v.png" alt="test evaluation results" width="562" height="159"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Upload models to S3
&lt;/h2&gt;

&lt;p&gt;We are saving the &lt;strong&gt;final&lt;/strong&gt; model, &lt;strong&gt;best&lt;/strong&gt; model, and &lt;strong&gt;training history&lt;/strong&gt; to S3.&lt;br&gt;
After running all the cells in all three notebooks (one for each dataset version), your bucket should contain a new &lt;code&gt;models/&lt;/code&gt; directory with the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;s3://YOUR-BUCKET-NAME/

models/
├── asl_cnn_raw_best.keras
├── asl_cnn_raw_final.keras
├── training_history_raw.csv
├── asl_cnn_filtered_best.keras
├── asl_cnn_filtered_final.keras
├── training_history_filtered.csv
├── asl_cnn_edges_best.keras
├── asl_cnn_edges_final.keras
└── training_history_edges.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Which model is the best?
&lt;/h2&gt;

&lt;p&gt;After running the notebook for 3 dataset versions (raw, Gaussian-filtered and Canny edge), it is interesting to find out which data resulted in the best model performance.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dataset Representation&lt;/th&gt;
&lt;th&gt;Loss&lt;/th&gt;
&lt;th&gt;Accuracy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Raw RGB&lt;/td&gt;
&lt;td&gt;0.0324&lt;/td&gt;
&lt;td&gt;99.34%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Canny Edges&lt;/td&gt;
&lt;td&gt;0.1291&lt;/td&gt;
&lt;td&gt;95.51%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gaussian Filtered&lt;/td&gt;
&lt;td&gt;0.2972&lt;/td&gt;
&lt;td&gt;90.11%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It turns out that the optimal performance (highest accuracy, lowest loss) was achieved using raw RGB images. One possible reason is that raw RGB images retain rich color information, gradients, and skin texture. Gaussian filtering may blur high-frequency finger boundaries, while Canny edge detection may discard useful internal hand details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this part, we used three dataset versions to train CNN models from scratch. The best performance was achieved using raw RGB images.&lt;/p&gt;

&lt;p&gt;We will keep three best models (&lt;code&gt;asl_cnn_raw_best.keras&lt;/code&gt;, &lt;code&gt;asl_cnn_filtered_best.keras&lt;/code&gt;, &lt;code&gt;asl_cnn_edges_best.keras&lt;/code&gt;) in S3 for now. In the next part, we will deploy these models to use in an ASL prediction app. Stay tuned!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>asl</category>
      <category>computervision</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>[Part 1] Your first steps in Computer Vision on AWS: ASL dataset + preprocessing</title>
      <dc:creator>Darya Petrashka</dc:creator>
      <pubDate>Fri, 23 Oct 2026 11:37:58 +0000</pubDate>
      <link>https://dev.to/dashapetr/part-1-your-first-steps-in-computer-vision-on-aws-asl-dataset-preprocessing-4h5p</link>
      <guid>https://dev.to/dashapetr/part-1-your-first-steps-in-computer-vision-on-aws-asl-dataset-preprocessing-4h5p</guid>
      <description>&lt;p&gt;This is the first part of the series "Your first steps in Computer Vision on AWS". If you are just starting, this tutorial will guide you step by step from the initial dataset to a deployed app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;Computer vision (CV) can help us to solve many problems. Sign Language Recognition (SLR) addresses the communication barrier between Deaf and Hard of Hearing (DHH) individuals and hearing non-signers. Our system should provide an automated character transcription without requiring human interpreters.&lt;/p&gt;

&lt;p&gt;Fact: Currently, more than 1.5 billion people (nearly 20% of the global population) live with hearing loss; 430 million of them have disabling hearing loss. [Source: &lt;a href="https://www.who.int/health-topics/hearing-loss#tab=tab_2" rel="noopener noreferrer"&gt;World Health Organization&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;The core purpose of CV in this domain is to transform high-dimensional, unstructured visual data (RGB images) into structured categories.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq5nbar588a10fswsfbed.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq5nbar588a10fswsfbed.jpg" alt="Sign language can be interpreted using CV" width="799" height="533"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@assadtanoli?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Assad Tanoli&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/a-young-girl-wearing-a-red-vest-and-white-shirt-NyEcJXFOz6A?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Dataset
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://www.kaggle.com/datasets/grassknoted/asl-alphabet" rel="noopener noreferrer"&gt;ASL Alphabet dataset (Kaggle)&lt;/a&gt; comprises 87,000 training images and 29 test images. Images are 200x200 pixels and in 3-channel RGB format. The dataset has 29 classes: 26 English letters (A-Z) and 3 control signs (SPACE, DELETE, NOTHING). As you can see, it is perfectly balanced: 3,000 images per class in the training set.&lt;/p&gt;

&lt;p&gt;One possible limitation is that images were captured under controlled, repeatable environments. They have static, isolated hand postures. We will see in later parts how we can address and potentially overcome such limitations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F836dvdpmlajdtdt8z6qc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F836dvdpmlajdtdt8z6qc.png" alt="Some examples of training images" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Which computer vision task type to select?
&lt;/h3&gt;

&lt;p&gt;Nice overview of CV task types is &lt;a href="https://www.ibm.com/think/topics/computer-vision" rel="noopener noreferrer"&gt;provided by IBM&lt;/a&gt;. Potentially, we can consider the following task types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Image Classification&lt;/strong&gt;: Categorizes an entire input image into a pre-defined class.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Object Detection&lt;/strong&gt;: Localizes target objects with spatial bounding boxes while simultaneously predicting class labels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semantic/Instance Segmentation&lt;/strong&gt;: Assigns class labels to individual pixels, creating fine-grained boundary masks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For our given dataset, the most sense would be to do &lt;strong&gt;image classification&lt;/strong&gt;: the task requires distinguishing among 29 discrete hand shape classes from pre-cropped images.&lt;/p&gt;

&lt;p&gt;❓ &lt;em&gt;Why not object detection?&lt;/em&gt; &lt;br&gt;
Hand regions are already centered within the frame, making bounding box detection redundant.&lt;/p&gt;

&lt;p&gt;❓ &lt;em&gt;Why not semantic/ instance segmentation?&lt;/em&gt; &lt;br&gt;
It has high annotation cost and computational latency, the images are not annotated for this task.&lt;/p&gt;
&lt;h2&gt;
  
  
  Uploading to S3
&lt;/h2&gt;

&lt;p&gt;After downloading &lt;a href="https://www.kaggle.com/datasets/grassknoted/asl-alphabet" rel="noopener noreferrer"&gt;the zipped archive from Kaggle&lt;/a&gt;, you will need to upload it to S3.&lt;/p&gt;

&lt;p&gt;One way is to use the management console. But with such amount of files, it could take more than a day!&lt;/p&gt;

&lt;p&gt;Much better option would be to use AWS CLI. (&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html" rel="noopener noreferrer"&gt;How to install/update AWS CLI?&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Then run the commands to configure the appropriate concurrency (considering you have the default profile):&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;aws configure set default.s3.max_concurrent_requests 50&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
  &lt;em&gt;(Maximum number of parallel requests allowed at once)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;aws configure set default.s3.max_queue_size 10000&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
  &lt;em&gt;(Maximum number of tasks allowed in the transfer queue)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;aws configure set default.s3.multipart_threshold 64MB&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
  &lt;em&gt;(File size threshold before switching to a multipart transfer)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Unzip the downloaded archive. To copy the files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd archive/asl_alphabet_train
aws s3 sync ./asl_alphabet_train s3://your-bucket/raw/asl_alphabet_train/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;

&lt;p&gt;So your data in the bucket is organized in the following way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;s3://YOUR-BUCKET-NAME/

raw/
└── asl_alphabet_train/
    ├── A/
    ├── B/
    └── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
markdown&lt;/p&gt;

&lt;p&gt;⚠️ Note: if any file failed to be uploaded, use this command to find which one:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;aws s3 sync ./asl_alphabet_train s3://your-bucket/raw/asl_alphabet_train/ --dryrun&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;aws s3 sync&lt;/code&gt; compares your source and destination, the &lt;code&gt;--dryrun&lt;/code&gt; output will print a list of only the files that have not been copied yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create SageMaker notebook instance
&lt;/h2&gt;

&lt;p&gt;Next, we need some compute to preprocess our data. One of the ways to do it on AWS is to &lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/howitworks-create-ws.html" rel="noopener noreferrer"&gt;create a SageMaker notebook instance&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since we are not training any model yet (only processing 200x200 images one at a time), a bare CPU instance with additional disk space would be enough.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ml.t3.medium&lt;/code&gt; general-purpose instance provides 2 vCPUs and 4 GiB of internal RAM. Because we are going to store the original dataset and its 2 preprocessed copies on the disk, we will need to add a 30-40 GB EBS volume.&lt;/p&gt;

&lt;p&gt;I created an &lt;code&gt;ml.t3.medium&lt;/code&gt; instance with a 50 GB EBS volume:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm7yw3f7jejs98uo7fsjz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm7yw3f7jejs98uo7fsjz.png" alt="ml.t3.medium instance configuration" width="323" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pricing: &lt;code&gt;t3.medium&lt;/code&gt; is one of the cheapest options. The exact price can vary depending on the region; see &lt;a href="https://aws.amazon.com/ec2/pricing/on-demand/" rel="noopener noreferrer"&gt;this page for on-demand pricing reference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Don't forget to stop and terminate your instance once the data is processed and uploaded to S3.&lt;/strong&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Let's preprocess our data
&lt;/h2&gt;

&lt;p&gt;Once the notebook instance is ready, you can &lt;strong&gt;Open Jupyter / Open JupyterLab&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Upload the &lt;code&gt;data_preprocessing.ipynb&lt;/code&gt; Jupyter notebook &lt;a href="https://github.com/dashapetr/Computer_Vision_ASL_AWS/blob/main/sagemaker_notebooks/data_preprocessing.ipynb" rel="noopener noreferrer"&gt;from the GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Run cell by cell. You might need to restart the Kernel after running pip install of libraries. (first cell)&lt;/p&gt;

&lt;p&gt;⚠️ Don't forget to replace the placeholder and put your S3 bucket name:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;BUCKET = "YOUR-BUCKET-NAME"&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  What it does (high-level):
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Downloads the data from S3&lt;/li&gt;
&lt;li&gt;Creates the train/validation/test split&lt;/li&gt;
&lt;li&gt;Separately applies Gaussian filtering and Canny edge detection to each image&lt;/li&gt;
&lt;li&gt;Uploads the preprocessed images to S3 &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Why do we need to preprocess data?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Gaussian filtering&lt;/strong&gt; subtly softens the image, preserving color while smoothing high-frequency noise. &lt;br&gt;
In our code, it is achieved using a simple function from the &lt;a href="https://pypi.org/project/opencv-python/" rel="noopener noreferrer"&gt;OpenCV package&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="n"&gt;filtered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GaussianBlur&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;GAUSSIAN_KERNEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;sigmaX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;GAUSSIAN_SIGMA&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are using (5, 5) as &lt;code&gt;GAUSSIAN_KERNEL&lt;/code&gt; and 1.0 as &lt;code&gt;GAUSSIAN_SIGMA&lt;/code&gt;. Adjust these values to regulate the amount of smoothing. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.opencv.org/4.13.0/d4/d13/tutorial_py_filtering.html" rel="noopener noreferrer"&gt;Learn more about Gaussian blurring&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Canny edge detection&lt;/strong&gt; isolates the high-contrast skeletal boundaries of hand postures and finger configurations while discarding background textures and skin illumination gradients.&lt;br&gt;
In our code, it is achieved in 2 steps. First, we convert the image to grayscale:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="n"&gt;gray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cvtColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COLOR_BGR2GRAY&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we use a simple function from the &lt;a href="https://pypi.org/project/opencv-python/" rel="noopener noreferrer"&gt;OpenCV package&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="n"&gt;edges&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Canny&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;gray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;threshold1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CANNY_LOW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;threshold2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CANNY_HIGH&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We specified 100 and 200 as &lt;code&gt;CANNY_LOW&lt;/code&gt; and &lt;code&gt;CANNY_HIGH&lt;/code&gt; thresholds. These values help to decide which faint edges are real and which are just random noise, ensuring that true object boundaries stay connected without breaking up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.opencv.org/4.13.0/da/d22/tutorial_py_canny.html" rel="noopener noreferrer"&gt;Learn more about Canny Edge Detection&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here is an example of what a letter ' B ' would look like in a raw image, Gaussian-filtered image, and Canny edge image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5r7hl4890yw3auib1bei.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5r7hl4890yw3auib1bei.png" alt="Letter 'B' in raw image, Gaussian filtered image, and Canny edge image" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Preprocessed data and upload:
&lt;/h3&gt;

&lt;p&gt;The split ratio is 70% for train, 15% for validation, and 15% for held-out test.&lt;/p&gt;

&lt;p&gt;Our split sizes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;train        60,900 images&lt;/li&gt;
&lt;li&gt;validation   13,050 images&lt;/li&gt;
&lt;li&gt;test         13,050 images&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚠️ Note: In some sources, the final held-out dataset is called &lt;em&gt;'validation'&lt;/em&gt;. &lt;br&gt;
Here, we are using &lt;strong&gt;validation set&lt;/strong&gt; for the model training/adjusting during multiple epochs. &lt;br&gt;
The final held-out dataset is called &lt;strong&gt;'test'&lt;/strong&gt; (we will do the final metric evaluation against it).&lt;/p&gt;

&lt;p&gt;Instead of physically moving raw data to separate folders during split, we use the CSV file to track which file corresponds to which split set.&lt;br&gt;
This file maps every image to its three representations.&lt;/p&gt;

&lt;p&gt;The file contains several columns: &lt;em&gt;'split', 'label', 'original_path', 'filtered_path', 'edge_path'&lt;/em&gt;.&lt;br&gt;
Our code in the following part will read file paths from the CSV and take the corresponding file from the required split. &lt;/p&gt;

&lt;p&gt;Here is what  this CSV file looks like (truncated):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdtcwgbtqievpwosrxmmm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdtcwgbtqievpwosrxmmm.png" alt="CSV file to track images" width="794" height="67"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After running all the notebook cells, the data is uploaded to S3. Your bucket should have a new &lt;code&gt;processed/&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;s3://YOUR-BUCKET-NAME/

processed/
├── filtered/
│   ├── train/
│   ├── validation/
│   └── test/
│
├── edges/
│   ├── train/
│   ├── validation/
│   └── test/
│
└── manifest.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, the full code in Jupyter notebook is available &lt;a href="https://github.com/dashapetr/Computer_Vision_ASL_AWS/blob/main/sagemaker_notebooks/data_preprocessing.ipynb" rel="noopener noreferrer"&gt;in the GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this part, we uploaded the ASL dataset to S3 and created a SageMaker notebook instance. By running the Jupyter notebook, we applied Gaussian filtering and Canny edge detection processing to raw images. Finally, we uploaded processed images to S3. &lt;/p&gt;

&lt;p&gt;We will keep all 3 image versions to compare which image representation would give the best model performance. In the next part, we will train a CNN from scratch. Stay tuned!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>asl</category>
      <category>computervision</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Community Builders – Christmas Edition</title>
      <dc:creator>Darya Petrashka</dc:creator>
      <pubDate>Tue, 20 Dec 2022 07:07:00 +0000</pubDate>
      <link>https://dev.to/aws-builders/community-builders-christmas-edition-3j56</link>
      <guid>https://dev.to/aws-builders/community-builders-christmas-edition-3j56</guid>
      <description>&lt;h2&gt;
  
  
  What surprises you most about the community builders program?
&lt;/h2&gt;

&lt;p&gt;It is a world-wide global program! I meet here a lot of people from different cultures, countries, backgrounds. But what unites us is the passion to AWS, tech. And we always can find a common language!&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s your background and your experience with AWS?
&lt;/h2&gt;

&lt;p&gt;I started my exiting AWS journey last April, first I got hands-on with Lambda, S3, SageMaker (since I am a Data Scientist). Then when I was preparing to Machine Learning certification, I discovered services like Athena, Glue, Kinesis, etc. Thanks to the program, I got Data Analytics certified. Now I am building the project based on Lex, Polly, Lambda, S3.&lt;br&gt;
And this is a non-stop learning, very fascinating!&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the biggest benefit you see from the program?
&lt;/h2&gt;

&lt;p&gt;I would say that these are the possibilities that the program provides. The program's benefits and content are made wisely, so you have a cool infrastructure to grow technically. With credits you can build whatever you want, with sessions and cloud academy courses you have resources to learn, if you are stuck, you have a community of people willing to help. Finally, you can share your knowledge with other people!&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the next swag item that you would like to get?
&lt;/h2&gt;

&lt;p&gt;A backpack or a T-shirt.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are you eating for dinner today? Share the recipe!
&lt;/h2&gt;

&lt;p&gt;My dinner is stupid simple: I just blender an apple, a banana, a tangerine, a carrot and some parsley (or spinach) into a smoothie.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is there anything else you would like to say about the community builders program in 2022?
&lt;/h2&gt;

&lt;p&gt;It's hard to express in words how happy I am to be a part of this  awesome program! Thanks a lot! I am really looking forward to the next year!&lt;/p&gt;

</description>
      <category>emptystring</category>
    </item>
  </channel>
</rss>
