diff --git a/.gitattributes b/.gitattributes
index a6344aac8c09253b3b630fb776ae94478aa0275b..bec828c530b345422b8f5b18b35f6a37106f7d75 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -33,3 +33,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.zst filter=lfs diff=lfs merge=lfs -text
*tfevents* filter=lfs diff=lfs merge=lfs -text
+AlphanumericQR.ttf filter=lfs diff=lfs merge=lfs -text
+BallpointPenNHK-Regular.ttf filter=lfs diff=lfs merge=lfs -text
+EULA[[:space:]]BallpointPenNHK.pdf filter=lfs diff=lfs merge=lfs -text
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/AlphanumericQR.ttf b/AlphanumericQR.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..2f621c9a10ba15a88d516c51e0ec18a3fc2b9db5
--- /dev/null
+++ b/AlphanumericQR.ttf
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c16ec58d9b2ece98c013a72666a031d4b13b7349d33b19e306b9966303121977
+size 105364
diff --git a/BallpointPenNHK-Regular.ttf b/BallpointPenNHK-Regular.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..3420ce041c9c012197a417bb9783757edb899e3b
--- /dev/null
+++ b/BallpointPenNHK-Regular.ttf
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:82108314e1dcd918c09403edc6ec88218f56af0628c95bfc1d475386d7b4ae83
+size 309684
diff --git a/Carnival.ttf b/Carnival.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..f90253b578e05c3288cc738153a9d42249b219fe
Binary files /dev/null and b/Carnival.ttf differ
diff --git a/Chesilin.ttf b/Chesilin.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..8e44b1baada1fbdab69f080e4a0601f3b73cc702
Binary files /dev/null and b/Chesilin.ttf differ
diff --git a/Daemon.otf b/Daemon.otf
new file mode 100644
index 0000000000000000000000000000000000000000..c3e763a8d630b86a755e9b0016475fbe3d464332
Binary files /dev/null and b/Daemon.otf differ
diff --git a/Daemon_Training.png b/Daemon_Training.png
new file mode 100644
index 0000000000000000000000000000000000000000..c570d30dcc98fa2087f342f7258f4a3fb7b16c2a
Binary files /dev/null and b/Daemon_Training.png differ
diff --git a/EULA BallpointPenNHK.pdf b/EULA BallpointPenNHK.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..5de6c5b8313195d2df7577643a71044a30b1ff05
--- /dev/null
+++ b/EULA BallpointPenNHK.pdf
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fa81b3b9cb5e2ea540922ade44185601ba9b2a745ce477f563dddf5351c51889
+size 643136
diff --git a/FortuneTeller.ttf b/FortuneTeller.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..6147250e879fe30cdbeb7a504f872a413b4bd036
Binary files /dev/null and b/FortuneTeller.ttf differ
diff --git a/Jajapanan.ttf b/Jajapanan.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..706f223b1952eb1c3565aa526d04310a67bd2cf2
Binary files /dev/null and b/Jajapanan.ttf differ
diff --git a/Kakuji.ttf b/Kakuji.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..ce95d5f0933a81e02e4f774c748f0dbd8f386aa0
Binary files /dev/null and b/Kakuji.ttf differ
diff --git a/Ling_Ling_-_Cost_vs_Accuracy.png b/Ling_Ling_-_Cost_vs_Accuracy.png
new file mode 100644
index 0000000000000000000000000000000000000000..a4f888e22b9dfddfcb002bbd88e5249395ea7a58
Binary files /dev/null and b/Ling_Ling_-_Cost_vs_Accuracy.png differ
diff --git a/Ling_Ling_-_Six_Predictions.png b/Ling_Ling_-_Six_Predictions.png
new file mode 100644
index 0000000000000000000000000000000000000000..5a08482b1c8407c7c835a9e6fe54a5cb6deda79a
Binary files /dev/null and b/Ling_Ling_-_Six_Predictions.png differ
diff --git a/LogisticRegression.md b/LogisticRegression.md
new file mode 100644
index 0000000000000000000000000000000000000000..60b04f672d30e9eba6d75f5c0785a738823931c4
--- /dev/null
+++ b/LogisticRegression.md
@@ -0,0 +1,22 @@
+7️⃣ **Cross Entropy Loss: Teaching AI to Learn Better** 🎯
+ - AI makes mistakes, so we **measure how bad they are** using a **loss function**.
+ - Cross Entropy Loss helps AI **learn from its mistakes** and get better.
+ - Instead of guessing randomly, the AI **adjusts itself to improve its answers**.
+
+8️⃣ **Backpropagation: AI Fixing Its Own Mistakes** 🔄
+ - AI learns by **guessing, checking, and fixing mistakes**.
+ - It uses **backpropagation** to update itself, just like **learning from practice**.
+ - This helps AI **get smarter every time it trains**.
+
+9️⃣ **Multi-Class Neural Networks: Picking the Best Answer** 🎨
+ - AI doesn’t always choose between **just two things**; sometimes, it picks from **many choices**!
+ - It uses **Softmax** to figure out which answer is **most likely**.
+ - This helps in **image recognition, language processing, and more**!
+
+🔟 **Activation Functions: Helping AI Think Faster** ⚡
+ - AI uses **activation functions** to **decide which patterns matter**.
+ - Three important ones:
+ - **Sigmoid** → Helps with probabilities.
+ - **Tanh** → Balances data better.
+ - **ReLU** → Fastest and most useful!
+ - These make AI **learn faster and make better decisions**!
diff --git a/MusicNotation.ttf b/MusicNotation.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..2b58ac61daf62bb1810e5b8a537be2f8d746fda2
Binary files /dev/null and b/MusicNotation.ttf differ
diff --git a/Photograph Signature.ttf b/Photograph Signature.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..883cdb835c684c4693974efe29f70401b9581730
Binary files /dev/null and b/Photograph Signature.ttf differ
diff --git a/PyTorchClass.zip b/PyTorchClass.zip
new file mode 100644
index 0000000000000000000000000000000000000000..61dd7add29f1a0df41acbef66237b33cf87d6a8f
--- /dev/null
+++ b/PyTorchClass.zip
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3d1c7a965cb19f8338176d8377fa077731290baeaa2844144c5ac4e0174cf0e5
+size 22431051
diff --git a/README.md b/README.md
index 4577c9214f131515f456700ba3ebda2bff908547..e4515dc1312722caaedd0385d62d7099e5ac7be8 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,608 @@
----
-title: EverythingIsAFont
-emoji: 🌍
-colorFrom: red
-colorTo: pink
-sdk: gradio
-sdk_version: 5.23.1
-app_file: app.py
-pinned: false
-license: mit
-short_description: Everything is a Font.
----
-
-Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
+
+# 🧠 **What is Logistic Regression?**
+Imagine you have a **robot** that tries to guess if a fruit is an 🍎 **apple** or a 🍌 **banana**.
+- The robot uses **Logistic Regression** to make its guess.
+- It looks at things like the fruit’s **color**, **shape**, and **size** to decide.
+- The robot gives a score from **0 to 1**:
+ - 0 → Definitely a banana 🍌
+ - 1 → Definitely an apple 🍎
+ - 0.5 → The robot is unsure 🤖
+
+## 🔥 **What does the notebook do?**
+1. **Makes fake data** → It creates pretend fruits with made-up colors and sizes.
+2. **Builds the Logistic Regression model** → This is the robot that learns how to guess.
+3. **Trains the robot** → It lets the robot practice guessing until it gets better.
+4. **Shows why bad initialization is bad** → If the robot starts with **wrong guesses**, it takes a long time to learn.
+ - Good start ➡️ 🟢 The robot learns fast.
+ - Bad start ➡️ 🔴 The robot takes forever or never learns properly.
+5. **Shows how to fix bad initialization** → We can **reinitialize** the robot with -**Random weights** to start with good guesses.
+
+
+# 🧠 **What is Cross-Entropy?**
+Imagine you are playing a **guessing game** with a 🦉 **wise owl**.
+- The owl has to guess if a fruit is an 🍎 **apple** or a 🍌 **banana**.
+- The owl makes a **prediction** (for example: 90% sure it’s an apple).
+- If the owl is **right**, it gets a ⭐️.
+- If the owl is **wrong**, it gets a 👎.
+
+**Cross-Entropy** is like a **scorekeeper**:
+- If the owl guesses correctly ➡️ **low score** 🟢 (good)
+- If the owl guesses wrong ➡️ **high score** 🔴 (bad)
+
+## 🔥 **What does the notebook do?**
+1. **Makes fake fruit data** → It creates pretend fruits with random colors and shapes.
+2. **Builds the Logistic Regression model** → This is the owl’s brain that makes guesses.
+3. **Trains the model with Cross-Entropy** → It helps the owl learn by keeping score.
+4. **Improves accuracy** → The owl gets better at guessing with practice by trying to lower its Cross-Entropy score.
+
+
+# 🧠 **What is Softmax?**
+Imagine you have a bag of colorful candies. Each candy represents a possible answer (like cat, dog, or bird). The **Softmax function** is like a magical machine that takes all the candies and tells you the **probability** of each one being picked.
+
+For example:
+- 🍬?->😺 **Cat** → 70% chance
+- 🍬?->🐶**Dog** → 20% chance
+- 🍬?->🐦 **Bird** → 10% chance
+
+Softmax makes sure that all the probabilities add up to **100%** (because one of them will definitely be the right answer).
+
+## 🔥 **What does the notebook do?**
+1. **Makes fake data** → It creates some pretend candies (data points) to practice with.
+2. **Builds the Softmax classifier** → This is the machine that guesses which candy you will pick based on its features.
+3. **Trains the model** → It lets the machine practice guessing so it gets better at it.
+4. **Shows the results** → It checks how good the machine is at guessing the correct candy.
+
+
+
+# 📚 Understanding Softmax and MNIST 🖊️
+
+## 1️⃣ What are we doing?
+We want to teach a computer how to recognize numbers (0-9) by looking at images. Just like how you can tell the difference between a "2" and a "5", we want the computer to do the same!
+
+## 2️⃣ What is MNIST? 🤔
+MNIST is a big collection of handwritten numbers. People have written digits (0-9) on paper, and all those images were put into a dataset for computers to learn from.
+
+## 3️⃣ What is a Softmax Classifier? 🤖
+A **Softmax Classifier** is like a decision-maker. When it sees a number, it checks **how sure** it is that the number is a 0, 1, 2, etc. It picks the number it is most confident about.
+
+Think of it like:
+- You see a blurry animal. 🐶🐱🐭
+- You think: "It **looks** like a dog, but **maybe** a cat."
+- You decide: "I'm **80% sure** it's a dog, **15% sure** it's a cat, and **5% sure** it's a mouse."
+- You pick the one you're most sure about → 🐶 Dog!
+
+That's exactly how Softmax works, but with numbers instead of animals!
+
+## 4️⃣ How do we train the computer? 🎓
+1. We **show** the computer many images of numbers. 📸
+2. It **tries to guess** what number is in the image. 🔢
+3. If it's wrong, we **correct** it and help it learn. 📚
+4. After training, it becomes **really good** at recognizing numbers! 🚀
+
+## 5️⃣ What will we do in the notebook? 📝
+- Load the MNIST dataset. 📊
+- Build a Softmax Classifier. 🏗️
+- Train it to recognize numbers. 🏋️♂️
+- Test if it works! ✅
+
+Let's start teaching our computer to recognize numbers! 🧠💡
+
+# 🧠 Building a Simple Neural Network! 🤖
+
+## 1️⃣ What are we doing? 🎯
+We are teaching a computer to recognize patterns! It will learn from examples and make smart guesses, just like how you learn from practice.
+
+## 2️⃣ What is a Neural Network? 🕸️
+A **neural network** is like a **tiny brain** inside a computer. It looks at data, finds patterns, and makes decisions.
+
+Imagine your brain trying to recognize your best friend:
+- Your **eyes** see their face. 👀
+- Your **brain** processes what you see. 🧠
+- You **decide**: "Hey, that's my friend!" 🎉
+
+A neural network does the same thing but with numbers!
+
+
+## 3️⃣ What is a Hidden Layer? 🤔
+A **hidden layer** is like a smart helper inside the network. It helps break down complex problems step by step.
+
+Think of it like:
+- 🏠 A house → **Too big to understand at once!**
+- 🧱 A hidden layer **breaks it down**: first walls, then windows, then doors!
+- 🏗️ This makes it easier to recognize and understand!
+
+## 4️⃣ How do we train the computer? 🎓
+1. We **show** it some data (like numbers or pictures). 👀
+2. It **guesses** what it sees. 🤔
+3. If it’s **wrong**, we **correct** it! ✏️
+4. After **practicing a lot**, it becomes **really good** at guessing. 🚀
+
+## 5️⃣ What will we do in the notebook? 📝
+- **Build a simple neural network** with **one hidden layer**. 🏗️
+- **Give it some data** to learn from. 📊
+- **Train it** so it gets better. 🏋️♂️
+- **Test it** to see if it works! ✅
+
+By the end, our computer will be **smarter** and ready to recognize patterns! 🧠💡
+
+# 🤖 Making a Smarter Neural Network! 🧠
+
+## 1️⃣ What are we doing? 🎯
+We are making a **better and smarter brain** for the computer! Instead of just one smart helper (neuron), we will have **many neurons working together**!
+
+## 2️⃣ What are Neurons? ⚡
+Neurons are like **tiny workers** inside a neural network. They take information, process it, and pass it along. The more neurons we have, the **smarter** our network becomes!
+
+Think of it like:
+- 🏗️ A simple house = **one worker** 🛠️ (slow)
+- 🏙️ A big city = **many workers** 🏗️ (faster & better!)
+
+## 3️⃣ Why More Neurons? 🤔
+More neurons mean:
+✅ The network **understands more details**.
+✅ It **learns better** and makes **fewer mistakes**.
+✅ It can solve **harder problems**!
+
+Imagine:
+- One person trying to solve a big puzzle 🧩 = **hard**
+- A team of people working together = **faster & easier!**
+
+## 4️⃣ How do we train it? 🎓
+1. **Give it some data** 📊
+2. **Let the neurons think** 🧠
+3. **If it’s wrong, we correct it** 📚
+4. **After practice, it gets really smart!** 🚀
+
+## 5️⃣ What will we do in the notebook? 📝
+- **Build a bigger neural network** with more neurons! 🏗️
+- **Feed it data to learn from** 📊
+- **Train it to get better** 🏋️♂️
+- **Test it to see how smart it is!** ✅
+
+By the end, our computer will be **super smart** at recognizing patterns! 🧠💡
+
+# 🤖 Teaching a Computer to Solve XOR! 🧠
+
+## 1️⃣ What are we doing? 🎯
+We are teaching a computer to understand a special kind of problem called **XOR**. It's like a puzzle where the answer is only "Yes" when things are different.
+
+## 2️⃣ What is XOR? ❌🔄✅
+XOR is a rule that works like this:
+- If two things are the **same** → ❌ NO
+- If two things are **different** → ✅ YES
+
+Example:
+| Input 1 | Input 2 | XOR Output |
+|---------|---------|------------|
+| 0 | 0 | 0 ❌ |
+| 0 | 1 | 1 ✅ |
+| 1 | 0 | 1 ✅ |
+| 1 | 1 | 0 ❌ |
+
+It's like a **light switch** that only turns on if one switch is flipped!
+
+## 3️⃣ Why is XOR tricky for computers? 🤔
+Basic computers **don’t understand XOR easily**. They need a **hidden layer** with **multiple neurons** to figure it out!
+
+## 4️⃣ What do we do in this notebook? 📝
+- **Create a neural network** with one hidden layer 🏗️
+- **Train it** to learn the XOR rule 🎓
+- **Try different numbers of neurons** (1, 2, 3...) to see what works best! ⚡
+
+By the end, our computer will **solve the XOR puzzle** and be smarter! 🧠🚀
+
+# 🧠 Teaching a Computer to Read Numbers! 🔢🤖
+
+## 1️⃣ What are we doing? 🎯
+We are training a **computer brain** to look at pictures of numbers (0-9) and guess what they are!
+
+## 2️⃣ What is the MNIST Dataset? 📸
+MNIST is a **big collection of handwritten numbers** that we use to teach computers how to recognize digits.
+
+## 3️⃣ How does the Computer Learn? 🏗️
+- The computer looks at **lots of examples** of numbers. 👀
+- It tries to guess what number each image shows. 🤔
+- If it’s **wrong**, we help it learn and get better! 📚
+- After **lots of practice**, it becomes really smart! 🚀
+
+## 4️⃣ What’s Special About This Network? 🤔
+We are using a **simple neural network** with **one hidden layer**. This layer helps the computer **understand patterns** in the numbers!
+
+## 5️⃣ What Will We Do in This Notebook? 📝
+- **Build a simple neural network** with **one hidden layer**. 🏗️
+- **Train it** to recognize numbers. 🎓
+- **Test it** to see how smart it is! ✅
+
+By the end, our computer will **read numbers just like you!** 🧠💡
+
+# ⚡ Making the Computer Think Better! 🧠
+
+## 1️⃣ What are we doing? 🎯
+We are learning about **activation functions** – special rules that help a computer **decide things**!
+
+## 2️⃣ What is an Activation Function? 🤔
+Think of a **light switch**! 💡
+- If you turn it **ON**, the light shines.
+- If you turn it **OFF**, the light is dark.
+
+Activation functions help a computer **decide** what to focus on, just like flipping a switch!
+
+## 3️⃣ Types of Activation Functions 🔢
+We will learn about:
+- **Sigmoid**: A soft switch that makes decisions slowly.
+- **Tanh**: A stronger version of Sigmoid.
+- **ReLU**: The fastest and strongest switch for learning!
+
+## 4️⃣ What Will We Do in This Notebook? 📝
+- **Learn about different activation functions** ⚡
+- **Try them in a neural network** 🏗️
+- **See which one works best** ✅
+
+By the end, we’ll know how computers **make smart choices!** 🤖
+
+# 🔢 Helping a Computer Read Numbers Better! 🧠🤖
+
+## 1️⃣ What are we doing? 🎯
+We are testing **three different activation functions** to see which one helps the computer **read numbers the best!**
+
+## 2️⃣ What is an Activation Function? 🤔
+An activation function helps the computer **decide things**!
+It’s like a **brain switch** that turns information **ON or OFF** so the computer can learn better.
+
+## 3️⃣ What Activation Functions Are We Testing? ⚡
+- **Sigmoid**: Soft decision-making. 🧐
+- **Tanh**: A stronger version of Sigmoid. 🔥
+- **ReLU**: The fastest and most powerful! ⚡
+
+## 4️⃣ What Will We Do in This Notebook? 📝
+- **Train a computer** to read handwritten numbers! 🔢
+- **Use different activation functions** and compare them. ⚡
+- **See which one works best** for accuracy! ✅
+
+By the end, we’ll know which function helps the computer **think the smartest!** 🧠🚀
+
+# 🧠 What is a Deep Neural Network? 🤖
+
+## 1️⃣ What are we doing? 🎯
+We are building a **Deep Neural Network (DNN)** to help a computer **understand and recognize numbers**!
+
+## 2️⃣ What is a Deep Neural Network? 🤔
+A Deep Neural Network is a **super smart computer brain** with **many layers**.
+Each layer **learns something new** and helps the computer make better decisions.
+
+Think of it like:
+👶 **A baby** trying to recognize a cat 🐱 → It might get confused!
+👦 **A child** learning from books 📚 → Gets better at it!
+🧑 **An expert** who has seen many cats 🏆 → Can recognize them instantly!
+
+A **Deep Neural Network** works the same way—it **learns step by step**!
+
+## 3️⃣ Why is a Deep Neural Network better? 🚀
+✅ **More layers** = **More learning!**
+✅ Can understand **complex patterns**.
+✅ Can make **smarter decisions**!
+
+## 4️⃣ What Will We Do in This Notebook? 📝
+- **Build a Deep Neural Network** with multiple layers 🏗️
+- **Train it** to recognize handwritten numbers 🔢
+- **Try different activation functions** (Sigmoid, Tanh, ReLU) ⚡
+- **See which one works best!** ✅
+
+By the end, our computer will be **super smart** at recognizing patterns! 🧠🚀
+
+# 🌀 Teaching a Computer to See Spirals! 🤖
+
+## 1️⃣ What are we doing? 🎯
+We are teaching a **computer brain** to look at points in a spiral shape and **figure out which group they belong to**!
+
+## 2️⃣ Why is this tricky? 🤔
+The points are **twisted into spirals** 🌀, so the computer needs to be **really smart** to tell them apart.
+It needs a **deep neural network** to **understand the swirl**!
+
+## 3️⃣ How does the Computer Learn? 🏗️
+- It looks at **many points** 👀
+- It **guesses** which spiral they belong to ❓
+- If it’s **wrong**, we help it fix mistakes! 🚀
+- After **lots of practice**, it gets really good at sorting them! ✅
+
+## 4️⃣ What’s Special About This Network? 🧠
+- We use **ReLU activation** ⚡ to make learning **faster and better**!
+- We **train it** to separate the spiral points into **different colors**! 🎨
+
+## 5️⃣ What Will We Do in This Notebook? 📝
+- **Build a deep neural network** with **many layers** 🏗️
+- **Train it** to separate spirals 🌀
+- **Check if it gets them right**! ✅
+
+By the end, our computer will **see the spirals just like us!** 🧠✨
+
+# 🎓 Teaching a Computer to Be Smarter with Dropout! 🤖
+
+## 1️⃣ What are we doing? 🎯
+We are training a **computer brain** to make better predictions by using **Dropout**!
+
+## 2️⃣ What is Dropout? 🤔
+Dropout is like **playing a game with one eye closed**! 👀
+- It makes the computer **forget** some parts of what it learned **on purpose**!
+- This helps it **not get stuck** memorizing the training examples.
+- Instead, it learns to **think better** and make **stronger predictions**!
+
+## 3️⃣ Why is Dropout Important? 🧠
+Imagine learning math but only using the same **five problems** over and over.
+- You’ll **memorize** them but struggle with new ones! 😕
+- Dropout **mixes things up** so the computer learns **general rules**, not just examples! 🚀
+
+## 4️⃣ What Will We Do in This Notebook? 📝
+- **Make some data** to train our computer. 📊
+- **Build a neural network** and use Dropout. 🏗️
+- **Train it using Batch Gradient Descent** (a way to help the computer learn step by step). 🏃
+- **See how Dropout helps prevent overfitting!** ✅
+
+By the end, our computer will **make smarter decisions** instead of just memorizing! 🧠✨
+
+
+# 📉 Teaching a Computer to Predict Numbers with Dropout! 🤖
+
+## 1️⃣ What is Regression? 🤔
+Regression is when a computer **learns from past numbers** to **predict future numbers**!
+For example:
+- If you save **$5 every week**, how much will you have in **10 weeks**? 💰
+- The computer **looks at patterns** and **makes a smart guess**!
+
+## 2️⃣ Why Do We Need Dropout? 🚀
+Sometimes, the computer **memorizes too much** and doesn’t learn the real pattern. 😵
+Dropout **randomly turns off** parts of the computer’s learning, so it **thinks smarter** instead of just remembering numbers.
+
+## 3️⃣ What’s Happening in This Notebook? 📝
+- **We make number data** for the computer to learn from. 📊
+- **We build a model** using PyTorch to predict numbers. 🏗️
+- **We add Dropout** to stop the model from memorizing. ❌🧠
+- **We check if Dropout helps the model predict better!** ✅
+
+By the end, our computer will be **smarter at guessing numbers!** 🧠✨
+
+# 🏗️ Why Can't We Start with the Same Weights? 🤖
+
+## 1️⃣ What is Weight Initialization? 🤔
+When a computer **learns** using a neural network, it starts with **random numbers** (weights) and adjusts them over time to get better.
+
+## 2️⃣ What Happens if We Use the Same Weights? 🚨
+If all the starting weights are **the same**, the computer gets **confused**! 😵
+- Every neuron learns **the exact same thing** → No variety!
+- The network **doesn’t improve**, and learning **gets stuck**.
+
+## 3️⃣ What Will We Do in This Notebook? 📝
+- **Make a simple neural network** to test this. 🏗️
+- **Initialize all weights the same way** to see what happens. ⚖️
+- **Try using different random weights** and compare the results! 🎯
+
+By the end, we’ll see why **random weight initialization is important** for a smart neural network! 🧠✨
+
+# 🎯 Helping a Computer Learn Better with Xavier Initialization! 🤖
+
+## 1️⃣ What is Weight Initialization? 🤔
+When a neural network **starts learning**, it needs to begin with **some numbers** (called weights).
+If we **pick bad starting numbers**, the network **won't learn well**!
+
+## 2️⃣ What is Xavier Initialization? ⚖️
+Xavier Initialization is a **smart way** to pick these starting numbers.
+It **balances** them so they’re **not too big** or **too small**.
+This helps the computer **learn faster** and **make better decisions**! 🚀
+
+## 3️⃣ What Will We Do in This Notebook? 📝
+- **Build a neural network** to recognize handwritten numbers. 🔢
+- **Use Xavier Initialization** to set up good starting weights. 🎯
+- **Compare** how well the network learns! ✅
+
+By the end, we’ll see why **starting right** helps a neural network **become smarter!** 🧠✨
+
+# 🚀 Helping a Computer Learn Faster with Momentum! 🤖
+
+## 1️⃣ What is a Polynomial Function? 📈
+A polynomial function is a math equation with **powers** (like squared or cubed numbers).
+For example:
+- \( y = x^2 + 3x + 5 \)
+- \( y = x^3 - 2x^2 + x \)
+
+These are tricky for a computer to learn! 😵
+
+## 2️⃣ What is Momentum? ⚡
+Imagine rolling a ball down a hill. ⛰️🏀
+- If the ball **stops at every step**, it takes **a long time** to reach the bottom.
+- But if we give it **momentum**, it **keeps going** and moves faster! 🚀
+
+Momentum helps a neural network **move in the right direction** without getting stuck.
+
+## 3️⃣ What Will We Do in This Notebook? 📝
+- **Teach a computer to learn polynomial functions.** 📊
+- **Use Momentum** to help it learn faster. 🏃
+- **Compare it to normal learning** and see why Momentum is better! ✅
+
+By the end, we’ll see how **Momentum helps a neural network** learn tricky math problems **faster and smarter!** 🧠✨
+
+# 🏃♂️ Helping a Neural Network Learn Faster with Momentum! 🚀
+
+## 1️⃣ What is a Neural Network? 🤖
+A neural network is a **computer brain** that learns by **adjusting numbers (weights)** to make good predictions.
+
+## 2️⃣ What is Momentum? ⚡
+Imagine pushing a heavy box. 📦
+- If you **push and stop**, it moves slowly. 😴
+- But if you **keep pushing**, it **gains speed** and moves **faster**! 🚀
+
+Momentum helps a neural network **keep moving in the right direction** without getting stuck!
+
+## 3️⃣ What Will We Do in This Notebook? 📝
+- **Train a neural network** to recognize patterns. 🎯
+- **Use Momentum** to help it learn faster. 🏃♂️
+- **Compare it to normal learning** and see why Momentum is better! ✅
+
+By the end, we’ll see how **Momentum helps a neural network** become **faster and smarter!** 🧠✨
+
+# 🚀 Helping a Neural Network Learn Better with Batch Normalization! 🤖
+
+## 1️⃣ What is a Neural Network? 🧠
+A neural network is like a **computer brain** that learns by adjusting **numbers (weights)** to make smart decisions.
+
+## 2️⃣ What is Batch Normalization? ⚖️
+Imagine a race where everyone starts at **different speeds**. Some are too slow, and some are too fast. 🏃♂️💨
+Batch Normalization **balances the speeds** so everyone runs **smoothly together**!
+
+For a neural network, this means:
+- **Making learning faster** 🚀
+- **Stopping extreme values** that cause bad learning ❌
+- **Helping the network work better** with deep layers! 🏗️
+
+## 3️⃣ What Will We Do in This Notebook? 📝
+- **Train a neural network** to recognize patterns. 🎯
+- **Use Batch Normalization** to help it learn better. ⚖️
+- **Compare it to normal learning** and see the difference! ✅
+
+By the end, we’ll see why **Batch Normalization** makes neural networks **faster and smarter!** 🧠✨
+
+# 👀 How Do Computers See? Understanding Convolution! 🤖
+
+## 1️⃣ What is Convolution? 🔍
+Convolution is like **giving a computer glasses** to help it focus on parts of an image! 🕶️
+- It **looks at small parts** of a picture instead of the whole thing at once. 🖼️
+- It **finds patterns**, like edges, shapes, or textures. 🔲
+
+## 2️⃣ Why Do We Use It? 🎯
+Imagine finding **Waldo** in a giant picture! 🔎👦
+- Instead of looking at everything at once, we **scan** small parts at a time.
+- Convolution helps computers **scan images smartly** to recognize objects! 🏆
+
+## 3️⃣ What Will We Do in This Notebook? 📝
+- **Learn how convolution works** step by step. 🛠️
+- **See how it helps computers find patterns** in images. 🖼️
+- **Understand why convolution is used in AI** for image recognition! 🤖✅
+
+By the end, we’ll see how convolution helps computers **see and understand pictures like humans!** 🧠✨
+
+# 🖼️ How Do Computers See Images? Understanding Activation & Max Pooling! 🤖
+
+## 1️⃣ What is an Activation Function? ⚡
+Activation functions **help the computer make smart decisions**! 🧠
+- They decide **which patterns are important** in an image.
+- Without them, the computer wouldn’t know what to focus on! 🎯
+
+## 2️⃣ What is Max Pooling? 🔍
+Max Pooling is like **shrinking an image** while keeping the best parts!
+- It **takes the most important details** and removes extra noise. 🎛️
+- This makes the computer **faster and better at recognizing objects!** 🚀
+
+## 3️⃣ What Will We Do in This Notebook? 📝
+- **See how activation functions work** to find patterns. 🔎
+- **Learn how max pooling makes images smaller but useful.** 📉
+- **Understand why these tricks make AI smarter!** 🤖✅
+
+By the end, we’ll see how **activation & pooling help computers "see" images like we do!** 🧠✨
+
+# 🌈 How Do Computers See Color? Understanding Multiple Channel Convolution! 🤖
+
+## 1️⃣ What is a Channel in an Image? 🎨
+Think of a picture on your screen. 🖼️
+- A **black & white** image has **1 channel** (just light & dark). ⚫⚪
+- A **color image** has **3 channels**: **Red, Green, and Blue (RGB)!** 🌈
+
+Computers **combine these channels** to see full-color pictures!
+
+## 2️⃣ What is Multiple Channel Convolution? 🔍
+- Instead of looking at just one channel, the computer **processes all 3 (RGB)** at the same time. 🔴🟢🔵
+- This helps it **find edges, textures, and patterns in color images**! 🎯
+
+## 3️⃣ What Will We Do in This Notebook? 📝
+- **See how convolution works on multiple channels.** 👀
+- **Understand how computers recognize colors & details.** 🖼️
+- **Learn why this is important for AI and image recognition!** 🤖✅
+
+By the end, we’ll see how **computers process full-color images like we do!** 🧠✨
+
+# 🖼️ How Do Computers Recognize Pictures? Understanding CNNs! 🤖
+
+## 1️⃣ What is a Convolutional Neural Network (CNN)? 🧠
+A CNN is a special **computer brain** designed to **look at pictures** and find patterns! 🔍
+- It **scans an image** like our eyes do. 👀
+- It learns to recognize **shapes, edges, and objects**. 🎯
+- This helps AI **identify things in pictures**, like cats 🐱, dogs 🐶, or numbers 🔢!
+
+## 2️⃣ How Does a CNN Work? ⚙️
+A CNN has **layers** that help it learn step by step:
+1. **Convolution Layer** – Finds small details like edges and corners. 🔲
+2. **Pooling Layer** – Shrinks the image but keeps the important parts. 📉
+3. **Fully Connected Layer** – Makes the final decision! ✅
+
+## 3️⃣ What Will We Do in This Notebook? 📝
+- **Build a simple CNN** that can recognize images. 🏗️
+- **See how each layer helps the computer "see" better.** 👀
+- **Understand why CNNs are great at image recognition!** 🚀
+
+By the end, we’ll see how **CNNs help computers recognize pictures just like humans do!** 🧠✨
+
+---
+
+# 🖼️ Teaching a Computer to See Small Pictures! 🤖
+
+## 1️⃣ What is a CNN? 🧠
+A **Convolutional Neural Network (CNN)** is a special AI that **looks at pictures and finds patterns**! 🔍
+- It scans images **piece by piece** like a puzzle. 🧩
+- It learns to recognize **shapes, edges, and objects**. 🎯
+- CNNs help AI recognize **faces, animals, and numbers**! 🐱🔢👀
+
+## 2️⃣ Why Small Images? 📏
+Small images are **harder to understand** because they have **fewer details**!
+- A CNN needs to **work extra hard** to find important features. 💪
+- We use **smaller filters and layers** to capture details. 🎛️
+
+## 3️⃣ What Will We Do in This Notebook? 📝
+- **Train a CNN on small images.** 🏗️
+- **See how it learns to recognize patterns.** 🔎
+- **Understand why CNNs work well, even with tiny pictures!** 🚀
+
+By the end, we’ll see how **computers can recognize even small images with AI!** 🧠✨
+
+---
+
+# 🖼️ Teaching a Computer to See Small Pictures with Batches! 🤖
+
+## 1️⃣ What is a CNN? 🧠
+A **Convolutional Neural Network (CNN)** is a special AI that **looks at pictures and learns patterns**! 🔍
+- It **finds shapes, edges, and objects** in an image. 🎯
+- It helps AI recognize **faces, animals, and numbers**! 🐱🔢👀
+
+## 2️⃣ What is a Batch? 📦
+Instead of looking at **one image at a time**, the computer looks at **a group (batch) of images** at once!
+- This **makes learning faster**. 🚀
+- It helps the CNN **understand patterns better**. 🧠✅
+
+## 3️⃣ Why Small Images? 📏
+Small images have **fewer details**, so the CNN must **work harder to find patterns**. 💪
+- We **train in batches** to help the computer **learn faster and better**. 🎛️
+
+## 4️⃣ What Will We Do in This Notebook? 📝
+- **Train a CNN on small images using batches.** 🏗️
+- **See how it learns to recognize objects better.** 🔎
+- **Understand why batching helps AI train efficiently!** ⚡
+
+By the end, we’ll see how **CNNs learn faster and smarter with batches!** 🧠✨
+
+---
+
+# 🖼️ Teaching a Computer to Recognize Handwritten Numbers! 🤖
+
+## 1️⃣ What is a CNN? 🧠
+A **Convolutional Neural Network (CNN)** is a smart AI that **looks at pictures and learns patterns**! 🔍
+- It **finds shapes, lines, and curves** in images. 🔢
+- It helps AI recognize **digits and handwritten numbers**! ✏️
+
+## 2️⃣ Why Handwritten Numbers? 🔢
+Handwritten numbers are **tricky** because everyone writes differently!
+- A CNN must **learn the different ways** people write the same number.
+- This helps it **recognize digits** even if they are messy. 💡
+
+## 3️⃣ What Will We Do in This Notebook? 📝
+- **Train a CNN to classify images of handwritten numbers.** 🏗️
+- **See how it learns to recognize different digits.** 🔎
+- **Understand how AI can analyze images of handwritten numbers!** 🚀
+
+By the end, we’ll see how **computers can recognize handwritten numbers just like we do!** 🧠✨
diff --git a/ShallowNeuralNetwork.md b/ShallowNeuralNetwork.md
new file mode 100644
index 0000000000000000000000000000000000000000..379b63567dec3d162a79761cdf8fa3b932a4543b
--- /dev/null
+++ b/ShallowNeuralNetwork.md
@@ -0,0 +1,86 @@
+1️⃣ **Introduction to Neural Networks (One Hidden Layer)** 🤖
+ - A neural network is like a **thinking machine** that makes decisions.
+ - It **learns from data** and gets better over time.
+ - We build a network with **one hidden layer** to help it **think smarter**.
+
+2️⃣ **More Neurons, Better Learning!** 🧠
+ - If a network **isn’t smart enough**, we add **more neurons**!
+ - More neurons = **better decision-making**.
+ - We train the network to **recognize patterns more accurately**.
+
+3️⃣ **Neural Networks with Multiple Inputs** 🔢
+ - Instead of just **one piece of data**, we give the network **many inputs**.
+ - This helps it **understand more complex problems**.
+ - Too many neurons = **overfitting (too specific)**, too few = **underfitting (too simple)**.
+
+4️⃣ **Multi-Class Neural Networks** 🎨
+ - Instead of choosing between **two options**, the network can choose **many!**
+ - It learns to **classify things into multiple groups**, like recognizing **different animals**.
+ - The Softmax function helps it **pick the best answer**.
+
+5️⃣ **Backpropagation: Learning from Mistakes** 🔄
+ - The network **makes a guess**, checks if it’s right, and **fixes itself**.
+ - It does this using **backpropagation**, which adjusts the neurons.
+ - This is how AI **gets smarter with time**!
+
+6️⃣ **Activation Functions: Helping AI Decide** ⚡
+ - Activation functions **control how neurons react**.
+ - Three common types:
+ - **Sigmoid** → Good for probabilities.
+ - **Tanh** → Helps balance data.
+ - **ReLU** → Fastest and most useful!
+ - These functions help the network **learn efficiently**.
+
+# 📖 AI Terms and Definitions (Based on the Videos) 🤖
+
+### 🧠 **Neural Network**
+A **computer brain** that learns by adjusting numbers (weights) to make decisions.
+
+### 🎯 **Classification**
+Teaching AI to **sort things into groups**, like recognizing cats 🐱 and dogs 🐶 in pictures.
+
+### ⚡ **Activation Function**
+A rule that helps AI **decide which information is important**. Examples:
+- **Sigmoid** → Soft decision-making.
+- **Tanh** → Balances positive and negative values.
+- **ReLU** → Fast and effective!
+
+### 🔄 **Backpropagation**
+AI’s way of **fixing mistakes** by looking at errors and adjusting itself.
+
+### 📉 **Loss Function**
+A **score** that tells AI **how wrong** it was, so it can improve.
+
+### 🚀 **Gradient Descent**
+A method that helps AI **learn step by step** by making small changes to improve.
+
+### 🏗️ **Hidden Layer**
+A **middle part of a neural network** that helps process complex information.
+
+### 🌀 **Softmax Function**
+Helps AI **choose the best answer** when there are multiple choices.
+
+### ⚖️ **Cross Entropy Loss**
+A way to measure **how well AI is learning** when making choices.
+
+### 📊 **Multi-Class Neural Networks**
+AI models that can **choose from many options**, not just two.
+
+### 🏎️ **Momentum**
+A trick that helps AI **learn faster** by keeping track of past updates.
+
+### 🔍 **Overfitting**
+When AI **memorizes too much** and struggles with new data.
+
+### 😕 **Underfitting**
+When AI **doesn’t learn enough** and makes bad predictions.
+
+### 🎨 **Convolutional Neural Network (CNN)**
+A special AI for **understanding images**, used in things like face recognition.
+
+### 📦 **Batch Processing**
+Instead of training on **one piece of data at a time**, AI looks at **many pieces at once** to learn faster.
+
+### 🏗️ **PyTorch**
+A tool that helps build and train neural networks easily.
+
diff --git a/SoftmaxRegression.md b/SoftmaxRegression.md
new file mode 100644
index 0000000000000000000000000000000000000000..bf567b6b49048099cec7fd6c530037825af799e5
--- /dev/null
+++ b/SoftmaxRegression.md
@@ -0,0 +1,16 @@
+🔢 **Softmax: Helping AI Pick the Best Answer** 🎯
+ - AI sometimes has **many choices**, not just **yes or no**.
+ - The **Softmax function** helps AI **decide which answer is most likely**.
+ - It looks at **all possibilities** and picks the **best one**!
+
+🖼️ **Softmax for Images: Teaching AI to Recognize Pictures** 🧠
+ - AI can look at a picture and **guess what it is**.
+ - It checks **different parts** of the image and compares them.
+ - Softmax helps AI **pick the right label** (like "cat" or "dog").
+
+📊 **Softmax in PyTorch: Making AI Smarter** ⚙️
+ - AI needs **training** to get better at choosing answers.
+ - PyTorch helps AI **use Softmax** to **learn from mistakes**.
+ - After training, AI **makes better predictions**!
+
+By the end, AI will **think smarter** and **recognize things better**! 🚀
diff --git a/UpperLower.svg b/UpperLower.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4a508527507bc58088c22e2717227cb9f364da4c
--- /dev/null
+++ b/UpperLower.svg
@@ -0,0 +1,309 @@
+
+
+
diff --git a/ZXX Bold.otf b/ZXX Bold.otf
new file mode 100644
index 0000000000000000000000000000000000000000..d15ed94c574c98b98be81447339adc6a06cebba2
Binary files /dev/null and b/ZXX Bold.otf differ
diff --git a/ZXX Camo.otf b/ZXX Camo.otf
new file mode 100644
index 0000000000000000000000000000000000000000..d30157ce79474f06d6e39825b6ff3c892cbf4f8e
Binary files /dev/null and b/ZXX Camo.otf differ
diff --git a/ZXX False.otf b/ZXX False.otf
new file mode 100644
index 0000000000000000000000000000000000000000..b58c928e936160fbede1b70395f818ab877e1234
Binary files /dev/null and b/ZXX False.otf differ
diff --git a/ZXX Noise.otf b/ZXX Noise.otf
new file mode 100644
index 0000000000000000000000000000000000000000..c48b02a905e875e9e464da2aed65d4da42ec6f1b
Binary files /dev/null and b/ZXX Noise.otf differ
diff --git a/ZXX Sans.otf b/ZXX Sans.otf
new file mode 100644
index 0000000000000000000000000000000000000000..e5ded3c565512db10c2309dd71869ff620f725c2
Binary files /dev/null and b/ZXX Sans.otf differ
diff --git a/ZXX Xed.otf b/ZXX Xed.otf
new file mode 100644
index 0000000000000000000000000000000000000000..65569a5ae190f4d4e8dd99ab00ef305b6d3158ea
Binary files /dev/null and b/ZXX Xed.otf differ
diff --git a/after_logistic.png b/after_logistic.png
new file mode 100644
index 0000000000000000000000000000000000000000..51ce70d5c9e3aa0b3032463ed9473c0d43fb86ab
Binary files /dev/null and b/after_logistic.png differ
diff --git a/after_shallow.png b/after_shallow.png
new file mode 100644
index 0000000000000000000000000000000000000000..afcd33eb0443791d59486b44cfb46f58e7ffdbf1
Binary files /dev/null and b/after_shallow.png differ
diff --git a/after_softmax.png b/after_softmax.png
new file mode 100644
index 0000000000000000000000000000000000000000..a0e7de6649686bdd286310266634799cc942ae73
Binary files /dev/null and b/after_softmax.png differ
diff --git a/after_training_words.png b/after_training_words.png
new file mode 100644
index 0000000000000000000000000000000000000000..164017f1e0b88bfa87693a24461b1c652d4b6483
Binary files /dev/null and b/after_training_words.png differ
diff --git a/after_training_words_Chesilin.png b/after_training_words_Chesilin.png
new file mode 100644
index 0000000000000000000000000000000000000000..f69dc0d13ebf7cb0e629f0a50f425e543bc98ecb
Binary files /dev/null and b/after_training_words_Chesilin.png differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000000000000000000000000000000000000..b879d1d5de7ccdf00fafa7a9c2dfcf1905a31002
--- /dev/null
+++ b/app.py
@@ -0,0 +1,219 @@
+import gradio as gr
+import torch
+import numpy as np
+import matplotlib.pyplot as plt
+from torch import nn, optim
+from torch.utils.data import DataLoader
+from io import StringIO
+import os
+import base64
+# Import your modules
+from logistic_regression import LogisticRegressionModel
+from softmax_regression import SoftmaxRegressionModel
+from shallow_neural_network import ShallowNeuralNetwork
+import convolutional_neural_networks
+from dataset_loader import CustomMNISTDataset
+from final_project import train_final_model, get_dataset_options, FinalCNN
+import torchvision.transforms as transforms
+
+import torch
+import matplotlib.pyplot as plt
+from matplotlib import font_manager
+import matplotlib.pyplot as plt
+def number_to_char(number):
+ if 0 <= number <= 9:
+ return str(number) # 0-9
+ elif 10 <= number <= 35:
+ return chr(number + 87) # a-z (10 -> 'a', 35 -> 'z')
+ elif 36 <= number <= 61:
+ return chr(number + 65) # A-Z (36 -> 'A', 61 -> 'Z')
+ else:
+ return ''
+
+def visualize_predictions_svg(model, train_loader, stage):
+ """Visualizes predictions and returns SVG string for Gradio display."""
+ # Load the Daemon font
+ font_path = './Daemon.otf' # Path to your Daemon font
+ prop = font_manager.FontProperties(fname=font_path)
+
+ fig, ax = plt.subplots(6, 3, figsize=(12, 16)) # 6 rows and 3 columns for 18 images
+
+ model.eval()
+ images, labels = next(iter(train_loader))
+ images, labels = images[:18], labels[:18] # Get 18 images and labels
+
+ with torch.no_grad():
+ outputs = model(images)
+ _, predictions = torch.max(outputs, 1)
+
+ for i in range(18): # Iterate over 18 images
+ ax[i // 3, i % 3].imshow(images[i].squeeze(), cmap='gray')
+
+ # Convert predictions and labels to characters
+ pred_char = number_to_char(predictions[i].item())
+ label_char = number_to_char(labels[i].item())
+
+ # Display = or != based on prediction
+ if pred_char == label_char:
+ title_text = f"{pred_char} = {label_char}"
+ color = 'green' # Green if correct
+ else:
+ title_text = f"{pred_char} != {label_char}"
+ color = 'red' # Red if incorrect
+
+ # Set title with Daemon font and color
+ ax[i // 3, i % 3].set_title(title_text, fontproperties=prop, fontsize=12, color=color)
+ ax[i // 3, i % 3].axis('off')
+
+
+ # Convert the figure to SVG
+ svg_str = figure_to_svg(fig)
+ save_svg_to_output_folder(svg_str, f"{stage}_predictions.svg") # Save SVG to output folder
+ plt.close(fig)
+
+ return svg_str
+
+def figure_to_svg(fig):
+ """Convert a matplotlib figure to SVG string."""
+ from io import StringIO
+ from matplotlib.backends.backend_svg import FigureCanvasSVG
+ canvas = FigureCanvasSVG(fig)
+ output = StringIO()
+ canvas.print_svg(output)
+ return output.getvalue()
+
+def save_svg_to_output_folder(svg_str, filename):
+ """Save the SVG string to the output folder."""
+ output_path = f'./output/{filename}' # Ensure your output folder exists
+ with open(output_path, 'w') as f:
+ f.write(svg_str)
+
+
+def plot_metrics_svg(losses, accuracies):
+ """Generate training metrics as SVG string."""
+ fig, ax = plt.subplots(1, 2, figsize=(12, 5))
+
+ ax[0].plot(losses, label='Loss', color='red')
+ ax[0].set_title('Training Loss')
+ ax[0].set_xlabel('Epoch')
+ ax[0].set_ylabel('Loss')
+ ax[0].legend()
+
+ ax[1].plot(accuracies, label='Accuracy', color='green')
+ ax[1].set_title('Training Accuracy')
+ ax[1].set_xlabel('Epoch')
+ ax[1].set_ylabel('Accuracy')
+ ax[1].legend()
+
+ plt.tight_layout()
+ svg_str = figure_to_svg(fig)
+ save_svg_to_output_folder(svg_str, "training_metrics.svg") # Save metrics SVG to output folder
+ plt.close(fig)
+
+ return svg_str
+
+def train_model_interface(module, dataset_name, epochs=100, lr=0.01):
+ """Train the selected model with the chosen dataset."""
+ transform = transforms.Compose([
+ transforms.Resize((28, 28)),
+ transforms.Grayscale(num_output_channels=1),
+ transforms.ToTensor(),
+ transforms.Normalize(mean=[0.5], std=[0.5])
+ ])
+
+ # Load dataset using CustomMNISTDataset
+ train_dataset = CustomMNISTDataset(os.path.join("data", dataset_name, "raw"), transform=transform)
+ train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
+
+ # Select Model
+ if module == "Logistic Regression":
+ model = LogisticRegressionModel(input_size=1)
+ elif module == "Softmax Regression":
+ model = SoftmaxRegressionModel(input_size=2, num_classes=2)
+ elif module == "Shallow Neural Networks":
+ model = ShallowNeuralNetwork(input_size=2, hidden_size=5, output_size=2)
+ elif module == "Deep Networks":
+ import deep_networks
+ model = deep_networks.DeepNeuralNetwork(input_size=10, hidden_sizes=[20, 10], output_size=2)
+ elif module == "Convolutional Neural Networks":
+ model = convolutional_neural_networks.ConvolutionalNeuralNetwork()
+ elif module == "AI Calligraphy":
+ model = FinalCNN()
+ else:
+ return "Invalid module selection", None, None, None, None
+
+ # Visualize before training
+ before_svg = visualize_predictions_svg(model, train_loader, "Before")
+
+ # Train the model
+ criterion = nn.CrossEntropyLoss()
+ optimizer = optim.SGD(model.parameters(), lr=lr)
+
+ losses, accuracies = train_final_model(model, criterion, optimizer, train_loader, epochs)
+
+ # Visualize after training
+ after_svg = visualize_predictions_svg(model, train_loader, "After")
+
+ # Metrics SVG
+ metrics_svg = plot_metrics_svg(losses, accuracies)
+
+ return model, losses, accuracies, before_svg, after_svg, metrics_svg
+
+
+def list_datasets():
+ """List all available datasets dynamically"""
+ dataset_options = get_dataset_options()
+ if not dataset_options:
+ return ["No datasets found"]
+ return dataset_options
+
+### 🎯 Gradio Interface ###
+def run_module(module, dataset_name, epochs, lr):
+ """Gradio interface callback"""
+ # Train model
+ model, losses, accuracies, before_svg, after_svg, metrics_svg = train_model_interface(
+ module, dataset_name, epochs, lr
+ )
+
+ if model is None:
+ return "Error: Invalid selection.", None, None, None, None
+
+ # Simply pass the SVG strings to Gradio's gr.Image for rendering
+ return (
+ f"Training completed for {module} with {epochs} epochs.",
+ before_svg, # Pass raw SVG for before training
+ after_svg, # Pass raw SVG for after training
+ metrics_svg # Return training metrics SVG directly
+ )
+
+### 🌟 Gradio UI ###
+with gr.Blocks() as app:
+ with gr.Tab("Techniques"):
+ gr.Markdown("### 🧠 Select Model to Train")
+
+ module_select = gr.Dropdown(
+ choices=[
+ "AI Calligraphy"
+ ],
+ label="Select Module"
+ )
+
+ dataset_list = gr.Dropdown(choices=list_datasets(), label="Select Dataset")
+ epochs = gr.Slider(10, 1024, value=100, step=10, label="Epochs")
+ lr = gr.Slider(0.001, 0.1, value=0.01, step=0.001, label="Learning Rate")
+
+ train_button = gr.Button("Train Model")
+
+ output = gr.Textbox(label="Training Output")
+ before_svg = gr.HTML(label="Before Training Predictions")
+ after_svg = gr.HTML(label="After Training Predictions")
+ metrics_svg = gr.HTML(label="Metrics")
+
+ train_button.click(
+ run_module,
+ inputs=[module_select, dataset_list, epochs, lr],
+ outputs=[output, before_svg, after_svg, metrics_svg]
+ )
+
+# Launch Gradio app
+app.launch(server_name="127.0.0.1", server_port=5555, share=True)
diff --git a/before_logistic.png b/before_logistic.png
new file mode 100644
index 0000000000000000000000000000000000000000..5999d839c8fa1d3d100fe502f8ed0833221f4b85
Binary files /dev/null and b/before_logistic.png differ
diff --git a/before_shallow.png b/before_shallow.png
new file mode 100644
index 0000000000000000000000000000000000000000..6a9fb2fa1d650ea63c70c2e5b3feec4c8f609b32
Binary files /dev/null and b/before_shallow.png differ
diff --git a/before_softmax.png b/before_softmax.png
new file mode 100644
index 0000000000000000000000000000000000000000..8c617ef28dc13f1bc911ef22432db1cfa3bd42d4
Binary files /dev/null and b/before_softmax.png differ
diff --git a/bullets4.ttf b/bullets4.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..3e5491b1eb4c383277e67cf295b8dfea7569cc7f
Binary files /dev/null and b/bullets4.ttf differ
diff --git a/convolutional_neural_networks.md b/convolutional_neural_networks.md
new file mode 100644
index 0000000000000000000000000000000000000000..894d13399bdf2687a173d51dafd9c44db7d69328
--- /dev/null
+++ b/convolutional_neural_networks.md
@@ -0,0 +1,703 @@
+l🎵 **Music Playing**
+
+👋 **Welcome!** Today, we’re learning about **Convolution** in Neural Networks! 🧠🖼️
+
+## 🤔 What is Convolution?
+Convolution helps computers **understand pictures** by looking at **patterns** instead of exact positions! 🖼️🔍
+
+Imagine you have **two images** that look almost the same, but one is a little **moved**.
+A computer might think they are totally **different**! 😲
+**Convolution fixes this problem!** ✅
+
+---
+
+## 🛠️ How Convolution Works
+
+We use something called a **kernel** (a small filter 🔲) that slides over an image.
+It **checks different parts** of the picture and creates a new image called an **activation map**!
+
+1️⃣ The **image** is a grid of numbers 🖼️
+2️⃣ The **kernel** is a small grid 🔳 that moves across the image
+3️⃣ It **multiplies** numbers in the image with the numbers in the kernel ✖️
+4️⃣ The results are **added together** ➕
+5️⃣ We move to the next spot and **repeat!** 🔄
+6️⃣ The final result is the **activation map** 🎯
+
+---
+
+## 📏 How Big is the Activation Map?
+
+The size of the **activation map** depends on:
+- **M (image size)** 📏
+- **K (kernel size)** 🔳
+- **Stride** (how far the kernel moves) 👣
+
+Formula:
+```
+New size = (Image size - Kernel size) + 1
+```
+
+Example:
+- **4×4 image** 📷
+- **2×2 kernel** 🔳
+- Activation map = **3×3** ✅
+
+---
+
+## 👣 What is Stride?
+
+Stride is **how far** the kernel moves each time!
+- **Stride = 1** ➝ Moves **one step** at a time 🐢
+- **Stride = 2** ➝ Moves **two steps** at a time 🚶♂️
+- **Bigger stride** = **Smaller** activation map! 📏
+
+---
+
+## 🛑 What is Zero Padding?
+
+Sometimes, the kernel **doesn’t fit** perfectly in the image. 😕
+So, we **add extra rows and columns of zeros** around the image! 0️⃣0️⃣0️⃣
+
+This makes sure the **kernel covers everything**! ✅
+
+Formula:
+```
+New Image Size = Old Size + 2 × Padding
+```
+
+---
+
+## 🎨 What About Color Images?
+
+For **black & white** images, we use **Conv2D** with **one channel** (grayscale). 🌑
+For **color images**, we use **three channels** (Red, Green, Blue - RGB)! 🎨🌈
+
+---
+
+## 🏆 Summary
+
+✅ Convolution helps computers **find patterns** in images!
+✅ We use a **kernel** to create an **activation map**!
+✅ **Stride & padding** change how the convolution works!
+✅ This is how computers **"see"** images! 👀🤖
+
+---
+
+🎉 **Great job!** Now, let’s try convolution in the lab! 🏗️🤖✨
+
+-----------------------------------------------------------------
+
+🎵 **Music Playing**
+
+👋 **Welcome!** Today, we’re learning about **Activation Functions** and **Max Pooling**! 🚀🔢
+
+## 🤖 What is an Activation Function?
+
+Activation functions help a neural network **decide** what’s important! 🧠
+They change the values in the activation map to **help the model learn better**.
+
+---
+
+## 🔥 Example: ReLU Activation Function
+
+1️⃣ We take an **input image** 🖼️
+2️⃣ We apply **convolution** to create an **activation map** 📊
+3️⃣ We apply **ReLU (Rectified Linear Unit)**:
+ - **If a value is negative** ➝ Change it to **0** ❌
+ - **If a value is positive** ➝ Keep it ✅
+
+### 🛠 Example Calculation
+
+| Before ReLU | After ReLU |
+|-------------|------------|
+| -4 | 0 |
+| 0 | 0 |
+| 4 | 4 |
+
+All **negative numbers** become **zero**! ✨
+
+In PyTorch, we apply the ReLU function **after convolution**:
+
+```python
+import torch.nn.functional as F
+
+output = F.relu(conv_output)
+```
+
+---
+
+## 🌊 What is Max Pooling?
+
+Max Pooling helps the network **focus on important details** while making images **smaller**! 📏🔍
+
+### 🏗 How It Works
+
+1️⃣ We **divide** the image into small regions (e.g., **2×2** squares)
+2️⃣ We **keep only the largest value** in each region
+3️⃣ We **move the window** and repeat until we’ve covered the whole image
+
+### 📊 Example: 2×2 Max Pooling
+
+| Before Pooling | After Pooling |
+|--------------|--------------|
+| 1, **6**, 2, 3 | **6**, **8** |
+| 5, **8**, 7, 4 | **9**, **7** |
+| **9**, 2, 3, **7** | |
+
+**Only the biggest number** in each section is kept! ✅
+
+---
+
+## 🏆 Why Use Max Pooling?
+
+✅ **Reduces image size** ➝ Makes training faster! 🚀
+✅ **Ignores small changes** in images ➝ More stable results! 🔄
+✅ **Helps find important features** in the picture! 🖼️
+
+In PyTorch, we apply **Max Pooling** like this:
+
+```python
+import torch.nn.functional as F
+
+output = F.max_pool2d(activation_map, kernel_size=2, stride=2)
+```
+
+---
+
+🎉 **Great job!** Now, let’s try using activation functions and max pooling in our own models! 🏗️🤖✨
+
+------------------------------------------------------------------------------------------------------
+🎵 **Music Playing**
+
+👋 **Welcome!** Today, we’re learning about **Convolution with Multiple Channels**! 🖼️🤖
+
+## 🤔 What’s a Channel?
+A **channel** is like a layer of an image! 🌈
+- **Black & White Images** ➝ **1 channel** (grayscale) 🏳️
+- **Color Images** ➝ **3 channels** (Red, Green, Blue - RGB) 🎨
+
+Neural networks **see** images by looking at these channels separately! 👀
+
+---
+
+## 🎯 1. Multiple Output Channels
+
+Usually, we use **one kernel** to create **one activation map** 📊
+But what if we want to detect **different things** in an image? 🤔
+- **Solution:** Use **multiple kernels**! Each kernel **finds different features**! 🔍
+
+### 🔥 Example: Detecting Lines
+1️⃣ A **vertical line kernel** finds **vertical edges** 📏
+2️⃣ A **horizontal line kernel** finds **horizontal edges** 📐
+
+**More kernels = More ways to see the image!** 👀✅
+
+---
+
+## 🎨 2. Multiple Input Channels
+
+Color images have **3 channels** (Red, Green, Blue).
+To process them, we use **a separate kernel for each channel**! 🎨
+
+1️⃣ Apply a **Red kernel** to the Red part of the image 🔴
+2️⃣ Apply a **Green kernel** to the Green part of the image 🟢
+3️⃣ Apply a **Blue kernel** to the Blue part of the image 🔵
+4️⃣ **Add the results together** to get one activation map!
+
+This helps the neural network understand **colors and patterns**! 🌈
+
+---
+
+## 🔄 3. Multiple Input & Output Channels
+
+Now, let’s **combine everything**! 🚀
+- **Multiple input channels** (like RGB images)
+- **Multiple output channels** (different filters detecting different things)
+
+Each output channel gets its own **set of kernels** for each input channel.
+We **apply the kernels, add the results**, and get multiple **activation maps**! 🎯
+
+---
+
+## 🏗 Example in PyTorch
+
+```python
+import torch.nn as nn
+
+conv = nn.Conv2d(in_channels=3, out_channels=5, kernel_size=3)
+```
+
+This means:
+✅ **3 input channels** (Red, Green, Blue)
+✅ **5 output channels** (5 different filters detecting different things)
+
+---
+
+## 🏆 Why is This Important?
+
+✅ Helps the neural network find **different patterns** 🎨
+✅ Works for **color images** and **complex features** 🤖
+✅ Makes the network **more powerful**! 💪
+
+---
+
+🎉 **Great job!** Now, let’s try convolution with multiple channels in our own models! 🏗️🤖✨
+-----------------------------------------------------------------------------------------------
+🎵 **Music Playing**
+
+👋 **Welcome!** Today, we’re building a **CNN for MNIST**! 🏗️🔢
+MNIST is a dataset of **handwritten numbers (0-9)**. ✍️🖼️
+
+---
+
+## 🏗 CNN Structure
+
+📏 **Image Size:** 16×16 (to make training faster)
+🔄 **Layers:**
+- **First Convolution Layer** ➝ 16 output channels
+- **Second Convolution Layer** ➝ 32 output channels
+- **Final Layer** ➝ 10 output neurons (one for each digit)
+
+---
+
+## 🛠 Building the CNN in PyTorch
+
+### 📌 Step 1: Define the CNN
+
+```python
+import torch.nn as nn
+
+class CNN(nn.Module):
+ def __init__(self):
+ super(CNN, self).__init__()
+ self.conv1 = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=5, padding=2)
+ self.pool = nn.MaxPool2d(kernel_size=2)
+ self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=5, padding=2)
+ self.fc = nn.Linear(32 * 4 * 4, 10) # Fully connected layer (512 inputs, 10 outputs)
+
+ def forward(self, x):
+ x = self.pool(nn.ReLU()(self.conv1(x))) # First layer: Conv + ReLU + Pool
+ x = self.pool(nn.ReLU()(self.conv2(x))) # Second layer: Conv + ReLU + Pool
+ x = x.view(-1, 512) # Flatten the 4x4x32 output to 1D (512 elements)
+ x = self.fc(x) # Fully connected layer for classification
+ return x
+```
+
+---
+
+## 🔍 Understanding the Output Shape
+
+After **Max Pooling**, the image shrinks to **4×4 pixels**.
+Since we have **32 channels**, the total output is:
+```
+4 × 4 × 32 = 512 elements
+```
+Each neuron in the final layer gets **512 inputs**, and since we have **10 digits (0-9)**, we use **10 neurons**.
+
+---
+
+## 🔄 Forward Step
+
+1️⃣ **Apply First Convolution Layer** ➝ Activation ➝ Max Pooling
+2️⃣ **Apply Second Convolution Layer** ➝ Activation ➝ Max Pooling
+3️⃣ **Flatten the Output (4×4×32 → 512)**
+4️⃣ **Apply the Final Output Layer (10 Neurons for 10 Digits)**
+
+---
+
+## 🏋️♂️ Training the Model
+
+Check the **lab** to see how we train the CNN using:
+✅ **Backpropagation**
+✅ **Stochastic Gradient Descent (SGD)**
+✅ **Loss Function & Accuracy Check**
+
+---
+
+🎉 **Great job!** Now, let’s train our CNN to recognize handwritten digits! 🏗️🔢🤖
+------------------------------------------------------------------------------------
+🎵 **Music Playing**
+
+👋 **Welcome!** Today, we’re learning about **Convolutional Neural Networks (CNNs)!** 🤖🖼️
+
+## 🤔 What is a CNN?
+A **Convolutional Neural Network (CNN)** is a special type of neural network that **understands images!** 🎨
+It learns to find patterns, like:
+✅ **Edges** (lines & shapes)
+✅ **Textures** (smooth or rough areas)
+✅ **Objects** (faces, animals, letters)
+
+---
+
+## 🏗 How Does a CNN Work?
+
+A CNN is made of **three main steps**:
+
+1️⃣ **Convolution Layer** 🖼️➝🔍
+ - Uses **kernels** (small filters) to **detect patterns** in an image
+ - Creates an **activation map** that highlights important features
+
+2️⃣ **Pooling Layer** 🔄➝📏
+ - **Shrinks** the activation map to keep only the most important parts
+ - **Max Pooling** picks the **biggest** values in each small region
+
+3️⃣ **Fully Connected Layer** 🏗️➝🎯
+ - The final layer makes a **decision** (like cat 🐱 or dog 🐶)
+
+---
+
+## 🎨 Example: Detecting Lines
+
+We train a CNN to recognize **horizontal** and **vertical** lines:
+
+1️⃣ **Input Image (X)**
+2️⃣ **First Convolution Layer**
+ - Uses **two kernels** to create two **activation maps**
+ - Applies **ReLU** (activation function) to remove negative values
+ - Uses **Max Pooling** to make learning easier
+
+3️⃣ **Second Convolution Layer**
+ - Takes **two input channels** from the first layer
+ - Uses **two new kernels** to create **one activation map**
+ - Again, applies **ReLU + Max Pooling**
+
+4️⃣ **Flattening** ➝ Turns the 2D image into **1D data**
+5️⃣ **Final Prediction** ➝ Uses a **fully connected layer** to decide:
+ - `0` = **Vertical Line**
+ - `1` = **Horizontal Line**
+
+---
+
+## 🔄 How to Build a CNN in PyTorch
+
+### 🏗 CNN Constructor
+```python
+import torch.nn as nn
+
+class CNN(nn.Module):
+ def __init__(self):
+ super(CNN, self).__init__()
+ self.conv1 = nn.Conv2d(in_channels=1, out_channels=2, kernel_size=3, padding=1)
+ self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
+ self.conv2 = nn.Conv2d(in_channels=2, out_channels=1, kernel_size=3, padding=1)
+ self.fc = nn.Linear(49, 2) # Fully connected layer (49 inputs, 2 outputs)
+
+ def forward(self, x):
+ x = self.pool(nn.ReLU()(self.conv1(x))) # First layer: Conv + ReLU + Pool
+ x = self.pool(nn.ReLU()(self.conv2(x))) # Second layer: Conv + ReLU + Pool
+ x = x.view(-1, 49) # Flatten to 1D
+ x = self.fc(x) # Fully connected layer
+ return x
+```
+
+---
+
+## 🏋️♂️ Training the CNN
+
+We train the CNN using **backpropagation** and **gradient descent**:
+
+1️⃣ **Load the dataset** (images of lines) 📊
+2️⃣ **Create a CNN model** 🏗️
+3️⃣ **Define a loss function** (to measure mistakes) ❌
+4️⃣ **Choose an optimizer** (to improve learning) 🔄
+5️⃣ **Train the model** until it **gets better**! 🚀
+
+As training progresses:
+📉 **Loss goes down** ➝ Model makes fewer mistakes!
+📈 **Accuracy goes up** ➝ Model gets better at predictions!
+
+---
+
+## 🏆 Why Use CNNs?
+
+✅ **Finds patterns** in images 🔍
+✅ **Works with real-world data** (faces, animals, objects) 🖼️
+✅ **More efficient** than regular neural networks 💡
+
+---
+
+🎉 **Great job!** Now, let’s build and train our own CNN! 🏗️🤖✨
+----------------------------------------------------------------------
+
+🎵 **Music Playing**
+
+👋 **Welcome!** Today, we’re building a **CNN for MNIST**! 🏗️🖼️
+MNIST is a dataset of **handwritten numbers (0-9)**. ✍️🔢
+
+---
+
+## 🏗 CNN Structure
+
+📏 **Image Size:** 16×16 (to make training faster)
+🔄 **Layers:**
+- **First Convolution Layer** ➝ 16 output channels
+- **Second Convolution Layer** ➝ 32 output channels
+- **Final Layer** ➝ 10 output neurons (one for each digit)
+
+---
+
+## 🛠 Building the CNN in PyTorch
+
+### 🔹 Step 1: Define the CNN
+
+```python
+import torch.nn as nn
+
+class CNN(nn.Module):
+ def __init__(self):
+ super(CNN, self).__init__()
+ self.conv1 = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=5, padding=2)
+ self.pool = nn.MaxPool2d(kernel_size=2)
+ self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=5, padding=2)
+ self.fc = nn.Linear(32 * 4 * 4, 10) # Fully connected layer (512 inputs, 10 outputs)
+
+ def forward(self, x):
+ x = self.pool(nn.ReLU()(self.conv1(x))) # First layer: Conv + ReLU + Pool
+ x = self.pool(nn.ReLU()(self.conv2(x))) # Second layer: Conv + ReLU + Pool
+ x = x.view(-1, 512) # Flatten the 4x4x32 output to 1D (512 elements)
+ x = self.fc(x) # Fully connected layer for classification
+ return x
+```
+
+---
+
+## 🔍 Understanding the Output Shape
+
+After **Max Pooling**, the image shrinks to **4×4 pixels**.
+Since we have **32 channels**, the total output is:
+```
+4 × 4 × 32 = 512 elements
+```
+Each neuron in the final layer gets **512 inputs**, and since we have **10 digits (0-9)**, we use **10 neurons**.
+
+---
+
+## 🔄 Forward Step
+
+1️⃣ **Apply First Convolution Layer** ➝ Activation ➝ Max Pooling
+2️⃣ **Apply Second Convolution Layer** ➝ Activation ➝ Max Pooling
+3️⃣ **Flatten the Output (4×4×32 → 512)**
+4️⃣ **Apply the Final Output Layer (10 Neurons for 10 Digits)**
+
+---
+
+## 🏋️♂️ Training the Model
+
+Check the **lab** to see how we train the CNN using:
+✅ **Backpropagation**
+✅ **Stochastic Gradient Descent (SGD)**
+✅ **Loss Function & Accuracy Check**
+
+---
+
+🎉 **Great job!** Now, let’s train our CNN to recognize handwritten digits! 🏗️🔢🤖
+------------------------------------------------------------------------------------
+🎵 **Music Playing**
+
+👋 **Welcome!** Today, we’re learning how to use **Pretrained TorchVision Models**! 🤖🖼️
+
+## 🤔 What is a Pretrained Model?
+
+A **pretrained model** is a neural network that has already been **trained by experts** on a large dataset.
+✅ **Saves time** (no need to train from scratch) ⏳
+✅ **Works better** (already optimized) 🎯
+✅ **We only train the final layer** for our own images! 🔄
+
+---
+
+## 🔄 Using ResNet18 (A Pretrained Model)
+
+We will use **ResNet18**, a powerful model trained on **color images**. 🎨
+It has **skip connections** (we won’t go into details, but it helps learning).
+
+We only **replace the last layer** to match our dataset! 🔁
+
+---
+
+## 🛠 Steps to Use a Pretrained Model
+
+### 📌 Step 1: Load the Pretrained Model
+```python
+import torchvision.models as models
+
+model = models.resnet18(pretrained=True) # Load pretrained ResNet18
+```
+
+### 📌 Step 2: Normalize Images (Required for ResNet18)
+```python
+import torchvision.transforms as transforms
+
+transform = transforms.Compose([
+ transforms.Resize((224, 224)), # Resize image
+ transforms.ToTensor(), # Convert to tensor
+ transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # Normalize
+])
+```
+
+### 📌 Step 3: Prepare the Dataset
+Create a **dataset object** for your own images with **training and testing data**. 📊
+
+### 📌 Step 4: Replace the Output Layer
+- The **last hidden layer** has **512 neurons**
+- We create a **new output layer** for **our dataset**
+
+Example: **If we have 7 classes**, we create a layer with **7 outputs**:
+```python
+import torch.nn as nn
+
+for param in model.parameters():
+ param.requires_grad = False # Freeze pretrained layers
+
+model.fc = nn.Linear(512, 7) # Replace output layer (512 inputs → 7 outputs)
+```
+
+---
+
+## 🏋️♂️ Training the Model
+
+### 📌 Step 5: Create Data Loaders
+```python
+train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=15, shuffle=True)
+test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=10, shuffle=False)
+```
+
+### 📌 Step 6: Set Up Training
+```python
+import torch.optim as optim
+
+criterion = nn.CrossEntropyLoss() # Loss function
+optimizer = optim.Adam(model.fc.parameters(), lr=0.001) # Optimizer (only for last layer)
+```
+
+### 📌 Step 7: Train the Model
+1️⃣ **Set model to training mode** 🏋️
+```python
+model.train()
+```
+2️⃣ Train for **20 epochs**
+3️⃣ **Set model to evaluation mode** when predicting 📊
+```python
+model.eval()
+```
+
+---
+
+## 🏆 Why Use Pretrained Models?
+
+✅ **Saves time** (no need to train from scratch)
+✅ **Works better** (pretrained on millions of images)
+✅ **We only change one layer** for our dataset!
+
+---
+
+🎉 **Great job!** Now, try using a pretrained model for your own images! 🏗️🤖✨
+---------------------------------------------------------------------------------
+🎵 **Music Playing**
+
+👋 **Welcome!** Today, we’re learning how to use **GPUs in PyTorch**! 🚀💻
+
+## 🤔 Why Use a GPU?
+A **Graphics Processing Unit (GPU)** can **train models MUCH faster** than a CPU!
+✅ Faster computation ⏩
+✅ Better for large datasets 📊
+✅ Helps train deep learning models efficiently 🤖
+
+---
+
+## 🔥 What is CUDA?
+CUDA is a **special tool** made by **NVIDIA** that allows us to use **GPUs for AI tasks**. 🎮🚀
+In **PyTorch**, we use **torch.cuda** to work with GPUs.
+
+---
+
+## 🛠 Step 1: Check if a GPU is Available
+
+```python
+import torch
+
+# Check if a GPU is available
+torch.cuda.is_available() # Returns True if a GPU is detected
+```
+
+---
+
+## 🎯 Step 2: Set Up the GPU
+
+```python
+device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
+```
+
+- `"cuda:0"` = First available GPU 🎮
+- `"cpu"` = Use the CPU if no GPU is found
+
+---
+
+## 🏗 Step 3: Sending Tensors to the GPU
+
+In PyTorch, **data is stored in Tensors**.
+To move data to the GPU, use `.to(device)`.
+
+```python
+tensor = torch.randn(3, 3) # Create a random tensor
+tensor = tensor.to(device) # Move it to the GPU
+```
+
+✅ **Faster processing on the GPU!** ⚡
+
+---
+
+## 🔄 Step 4: Using a GPU with a CNN
+
+You **don’t need to change** your CNN code! Just **move the model to the GPU** after creating it:
+
+```python
+model = CNN() # Create CNN model
+model.to(device) # Move the model to the GPU
+```
+
+This **converts** all layers to **CUDA tensors** for GPU computation! 🎮
+
+---
+
+## 🏋️♂️ Step 5: Training a Model on a GPU
+
+Training is the same, but **you must send your data to the GPU**!
+
+```python
+for images, labels in train_loader:
+ images, labels = images.to(device), labels.to(device) # Move data to GPU
+ optimizer.zero_grad() # Clear gradients
+ outputs = model(images) # Forward pass (on GPU)
+ loss = criterion(outputs, labels) # Compute loss
+ loss.backward() # Backpropagation
+ optimizer.step() # Update weights
+```
+
+✅ **The model trains much faster!** 🚀
+
+---
+
+## 🎯 Step 6: Testing the Model
+
+For testing, **only move the images** (not the labels) to the GPU:
+
+```python
+for images, labels in test_loader:
+ images = images.to(device) # Move images to GPU
+ outputs = model(images) # Get predictions
+```
+
+✅ **Saves memory and speeds up testing!** ⚡
+
+---
+
+## 🏆 Summary
+
+✅ **GPUs make training faster** 🎮
+✅ Use **torch.cuda** to work with GPUs
+✅ Move **data & models** to the GPU with `.to(device)`
+✅ Training & testing are the same, but data **must be on the GPU**
+
+---
+
+🎉 **Great job!** Now, try training a model using a GPU in PyTorch! 🏗️🚀
diff --git a/convolutional_neural_networks.py b/convolutional_neural_networks.py
new file mode 100644
index 0000000000000000000000000000000000000000..a519d36977be1f79b5fe4126aa1c42b808939b9d
--- /dev/null
+++ b/convolutional_neural_networks.py
@@ -0,0 +1,69 @@
+import torch
+import torch.nn as nn
+import torch.optim as optim
+
+# Convolutional Neural Network Model
+class ConvolutionalNeuralNetwork(nn.Module):
+ def __init__(self):
+ super(ConvolutionalNeuralNetwork, self).__init__()
+ self.conv1 = nn.Conv2d(1, 16, kernel_size=5)
+ self.conv2 = nn.Conv2d(16, 32, kernel_size=5)
+ self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
+ self.fc1 = nn.Linear(32 * 4 * 4, 120)
+ self.fc2 = nn.Linear(120, 84)
+ self.fc3 = nn.Linear(84, 10)
+
+ def forward(self, x):
+ x = self.pool(torch.relu(self.conv1(x)))
+ x = self.pool(torch.relu(self.conv2(x)))
+ x = x.view(-1, 32 * 4 * 4)
+ x = torch.relu(self.fc1(x))
+ x = torch.relu(self.fc2(x))
+ return x # Return raw output without applying softmax
+
+
+# Training Function
+def train_model(model, criterion, optimizer, x_train, y_train, epochs=100):
+ for epoch in range(epochs):
+ model.train()
+ optimizer.zero_grad()
+ y_pred = model(x_train)
+ loss = criterion(y_pred, y_train)
+ loss.backward()
+ optimizer.step()
+ if (epoch+1) % 10 == 0:
+ print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}')
+
+import matplotlib.pyplot as plt # Added import for plotting
+
+# Example Usage
+if __name__ == "__main__":
+ # Sample Data
+ x_train = torch.randn(100, 1, 28, 28) # Example for MNIST
+ y_train = torch.randint(0, 10, (100,))
+
+ # Plotting the input data
+ for i in range(6):
+ plt.subplot(2, 3, i + 1)
+ plt.imshow(x_train[i].squeeze(), cmap='gray')
+ plt.title(f'Label: {y_train[i].item()}')
+ plt.axis('off')
+ plt.show()
+
+
+ model = ConvolutionalNeuralNetwork()
+
+ # Plotting the predictions
+ y_pred = model(x_train).detach().numpy()
+ plt.figure(figsize=(12, 6))
+ for i in range(6):
+ plt.subplot(2, 3, i + 1)
+ plt.imshow(x_train[i].squeeze(), cmap='gray')
+ plt.title(f'Predicted: {np.argmax(y_pred[i])}')
+ plt.axis('off')
+ plt.show()
+
+ criterion = nn.CrossEntropyLoss()
+ optimizer = optim.SGD(model.parameters(), lr=0.01)
+
+ train_model(model, criterion, optimizer, x_train, y_train)
diff --git a/dataset_loader.py b/dataset_loader.py
new file mode 100644
index 0000000000000000000000000000000000000000..bb1f0aa89f051019a931428d1f9651ee554dc916
--- /dev/null
+++ b/dataset_loader.py
@@ -0,0 +1,69 @@
+import os
+import numpy as np
+import gzip
+from PIL import Image
+from torchvision import transforms
+
+class CustomMNISTDataset:
+ def __init__(self, dataset_path, transform=None):
+ self.dataset_path = dataset_path
+ self.transform = transform
+ self.images, self.labels = self.load_dataset()
+
+ def load_dataset(self):
+ image_paths = []
+ label_paths = []
+
+ # Assuming the dataset consists of images and labels in the dataset path
+ for file in os.listdir(self.dataset_path):
+ if 'train-images-idx3-ubyte.gz' in file:
+ image_paths.append(os.path.join(self.dataset_path, file))
+ elif 'train-labels-idx1-ubyte.gz' in file:
+ label_paths.append(os.path.join(self.dataset_path, file))
+
+ if not image_paths or not label_paths:
+ raise ValueError(f"❌ Missing image or label files in {self.dataset_path}")
+
+ images = []
+ labels = []
+
+ # Assuming one image file and one label file
+ for img_path, label_path in zip(image_paths, label_paths):
+ images_data, labels_data = self.load_mnist_data(img_path, label_path)
+ images.extend(images_data)
+ labels.extend(labels_data)
+
+ return images, labels
+
+ def load_mnist_data(self, img_path, label_path):
+ """Load MNIST data from .gz files."""
+ with gzip.open(img_path, 'rb') as f:
+ # Skip the magic number and metadata
+ f.read(16)
+ # Read the image data
+ img_data = np.frombuffer(f.read(), dtype=np.uint8)
+ img_data = img_data.reshape(-1, 28, 28) # Reshape to 28x28 images
+
+ with gzip.open(label_path, 'rb') as f:
+ # Skip the magic number and metadata
+ f.read(8)
+ # Read the label data
+ label_data = np.frombuffer(f.read(), dtype=np.uint8)
+
+ images = [Image.fromarray(img) for img in img_data] # Convert each image to a PIL Image
+
+ # If you have any transformation, apply it here
+ if self.transform:
+ images = [self.transform(img) for img in images]
+
+ return images, label_data
+
+ def __len__(self):
+ """Return the total number of images in the dataset."""
+ return len(self.images)
+
+ def __getitem__(self, idx):
+ """Return a single image and its label at the given index."""
+ image = self.images[idx]
+ label = self.labels[idx]
+ return image, label
diff --git a/deep_networks.md b/deep_networks.md
new file mode 100644
index 0000000000000000000000000000000000000000..5693bf81a682754e38951984c84a0b17814169c8
--- /dev/null
+++ b/deep_networks.md
@@ -0,0 +1,356 @@
+🎵 **Music Playing**
+
+👋 **Welcome!** Today, we’re learning about **Deep Neural Networks**—a cool way computers learn! 🧠💡
+
+## 🤖 What is a Neural Network?
+Imagine a brain made of tiny switches called **neurons**. These neurons work together to make smart decisions!
+
+### 🟢 Input Layer
+This is where we give the network information, like pictures or numbers.
+
+### 🔵 Hidden Layers
+These layers are like **magic helpers** that figure out patterns!
+- More neurons = better learning 🤓
+- Too many neurons = can be **confusing** (overfitting) 😵
+
+### 🔴 Output Layer
+This is where the network **gives us answers!** 🏆
+
+---
+
+## 🏗 Building a Deep Neural Network in PyTorch
+
+We can **build a deep neural network** using PyTorch, a tool that helps computers learn. 🖥️
+
+### 🛠 Layers of Our Network
+1️⃣ **First Hidden Layer:** Has `H1` neurons.
+2️⃣ **Second Hidden Layer:** Has `H2` neurons.
+3️⃣ **Output Layer:** Decides the final answer! 🎯
+
+---
+
+## 🔄 How Does It Work?
+1️⃣ **Start with an input (x).**
+2️⃣ **Pass through each layer:**
+ - Apply **math functions** (like `sigmoid`, `tanh`, or `ReLU`).
+ - These help the network understand better! 🧩
+3️⃣ **Get the final answer!** ✅
+
+---
+
+## 🎨 Different Activation Functions
+Activation functions help the network **think better!** 🧠
+- **Sigmoid** ➝ Good for small problems 🤏
+- **Tanh** ➝ Works better for deeper networks 🌊
+- **ReLU** ➝ Super strong for big tasks! 🚀
+
+---
+
+## 🔢 Example: Recognizing Handwritten Numbers
+We train the network with **MNIST**, a dataset of handwritten numbers. 📝🔢
+- **Input:** 784 pixels (28x28 images) 📸
+- **Hidden Layers:** 50 neurons each 🤖
+- **Output:** 10 neurons (digits 0-9) 🔟
+
+---
+
+## 🚀 Training the Network
+We use **Stochastic Gradient Descent (SGD)** to teach the network! 📚
+- **Loss Function:** Helps the network learn from mistakes. ❌➡✅
+- **Validation Accuracy:** Checks how well the network is doing! 🎯
+
+---
+
+## 🏆 What We Learned
+✅ Deep Neural Networks have **many hidden layers**.
+✅ Different **activation functions** help improve performance.
+✅ The more layers we add, the **smarter** the network becomes! 💡
+
+---
+
+🎉 **Great job!** Now, let's build and train our own deep neural networks! 🏗️🤖✨
+-----------------------------------------------------------------------------------
+🎵 **Music Playing**
+
+👋 **Welcome!** Today, we’ll learn how to **build a deep neural network** in PyTorch using `nn.ModuleList`. 🧠💡
+
+## 🤖 Why Use `nn.ModuleList`?
+Instead of adding layers **one by one** (which takes a long time ⏳), we can **automate** the process! 🚀
+
+---
+
+## 🏗 Building the Neural Network
+
+We create a **list** called `layers` 📋:
+- **First item:** Input size (e.g., `2` features).
+- **Second item:** Neurons in the **first hidden layer** (e.g., `3`).
+- **Third item:** Neurons in the **second hidden layer** (e.g., `4`).
+- **Fourth item:** Output size (number of classes, e.g., `3`).
+
+---
+
+## 🔄 Constructing the Network
+
+### 🔹 Step 1: Create Layers
+- We loop through the list, taking **two elements at a time**:
+ - **First element:** Input size 🎯
+ - **Second element:** Output size (number of neurons) 🧩
+
+### 🔹 Step 2: Connecting Layers
+- First **hidden layer** ➝ Input size = `2`, Neurons = `3`
+- Second **hidden layer** ➝ Input size = `3`, Neurons = `4`
+- **Output layer** ➝ Input size = `4`, Output size = `3`
+
+---
+
+## ⚡ Forward Function
+
+We **pass data** through the network:
+1️⃣ **Apply linear transformation** to each layer ➝ Makes calculations 🧮
+2️⃣ **Apply activation function** (`ReLU`) ➝ Helps the network learn 📈
+3️⃣ **For the last layer**, we only apply **linear transformation** (since it's a classification task 🎯).
+
+---
+
+## 🎯 Training the Network
+
+The **training process** is similar to before! We:
+- Use a **dataset** 📊
+- Try **different combinations** of neurons and layers 🤖
+- See which setup gives the **best performance**! 🏆
+
+---
+
+🎉 **Awesome!** Now, let’s explore ways to make these networks even **better!** 🚀
+-----------------------------------------------------------------------------------
+🎵 **Music Playing**
+
+👋 **Welcome!** Today, we’re learning about **weight initialization** in Neural Networks! 🧠⚡
+
+## 🤔 Why Does Weight Initialization Matter?
+If we **don’t** choose good starting weights, our neural network **won’t learn properly**! 🚨
+Sometimes, **all neurons** in a layer get the **same weights**, which causes problems.
+
+---
+
+## 🚀 How PyTorch Handles Weights
+PyTorch **automatically** picks starting weights, but we can also set them **ourselves**! 🔧
+Let’s see what happens when we:
+- Set **all weights to 1** and **bias to 0** ➝ ❌ **Bad idea!**
+- Randomly choose weights from a **uniform distribution** ➝ ✅ **Better!**
+
+---
+
+## 🔄 The Problem with Random Weights
+We use a **uniform distribution** (random values between -1 and 1). But:
+- **Too small?** ➝ Weights don’t change much 🤏
+- **Too large?** ➝ **Vanishing gradient** problem 😵
+
+### 📉 What’s a Vanishing Gradient?
+If weights are **too big**, activations get **too large**, and the **gradient shrinks to zero**.
+That means the network **stops learning**! 🚫
+
+---
+
+## 🛠 Fixing the Problem
+
+### 🎯 Solution: Scale Weights Based on Neurons
+We scale the weight range based on **how many neurons** we have:
+- **2 neurons?** ➝ Scale by **1/2**
+- **4 neurons?** ➝ Scale by **1/4**
+- **100 neurons?** ➝ Scale by **1/100**
+
+This prevents the vanishing gradient issue! ✅
+
+---
+
+## 🔬 Different Weight Initialization Methods
+
+### 🏗 **1. Default PyTorch Method**
+- PyTorch **automatically** picks a range:
+ - **Lower bound:** `-1 / sqrt(L_in)`
+ - **Upper bound:** `+1 / sqrt(L_in)`
+
+### 🔵 **2. Xavier Initialization**
+- Best for **tanh** activation
+- Uses the **number of input and output neurons**
+- We apply `xavier_uniform_()` to set the weights
+
+### 🔴 **3. He Initialization**
+- Best for **ReLU** activation
+- Uses the **He initialization method**
+- We apply `he_uniform_()` to set the weights
+
+---
+
+## 🏆 Which One is Best?
+We compare:
+✅ **PyTorch Default**
+✅ **Xavier Method** (tanh)
+✅ **He Method** (ReLU)
+
+The **Xavier and He methods** help the network **learn faster**! 🚀
+
+---
+
+🎉 **Great job!** Now, let’s try different weight initializations and see what works best! 🏗️🔬
+------------------------------------------------------------------------------------------------
+🎵 **Music Playing**
+
+👋 **Welcome!** Today, we’re learning about **Gradient Descent with Momentum**! 🚀🔄
+
+## 🤔 What’s the Problem?
+Sometimes, when training a neural network, the model can get **stuck**:
+- **Saddle Points** ➝ Flat areas where learning stops 🏔️
+- **Local Minima** ➝ Not the best solution, but we get trapped 😞
+
+---
+
+## 🏃♂️ What is Momentum?
+Momentum helps the model **keep moving** even when it gets stuck! 💨
+It’s like rolling a ball downhill:
+- **Gradient (Force)** ➝ Tells us where to go 🏀
+- **Momentum (Mass)** ➝ Helps us keep moving even on flat surfaces ⚡
+
+---
+
+## 🔄 How Does It Work?
+
+### 🔹 Step 1: Compute Velocity
+- Velocity (`v`) = Old velocity (`v_k`) + Learning step (`gradient * learning rate`)
+- The **momentum term** (𝜌) controls how much we keep from the past.
+
+### 🔹 Step 2: Update Weights
+- New weight (`w_k+1`) = Old weight (`w_k`) - Learning rate * Velocity
+
+The bigger the **momentum**, the harder it is to stop moving! 🏃♂️💨
+
+---
+
+## ⚠️ Why Does It Help?
+
+### 🏔️ **Saddle Points**
+- **Without Momentum** ➝ Model **stops** moving in flat areas ❌
+- **With Momentum** ➝ Keeps moving **past** the flat spots ✅
+
+### ⬇ **Local Minima**
+- **Without Momentum** ➝ Gets **stuck** in a bad spot 😖
+- **With Momentum** ➝ Pushes through and **finds a better solution!** 🎯
+
+---
+
+## 🏆 Picking the Right Momentum
+
+- **Too Small?** ➝ Model gets **stuck** 😕
+- **Too Large?** ➝ Model **overshoots** the best answer 🚀
+- **Best Choice?** ➝ We test different values and pick what works! 🔬
+
+---
+
+## 🛠 Using Momentum in PyTorch
+Just add the **momentum** value to the optimizer!
+
+```python
+optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
+```
+
+In the lab, we test **different momentum values** on a dataset and see how they affect learning! 📊
+
+---
+
+🎉 **Great job!** Now, let’s experiment with momentum and see how it helps our model! 🏗️⚡
+------------------------------------------------------------------------------------------
+🎵 **Music Playing**
+
+👋 **Welcome!** Today, we’re learning about **Batch Normalization**! 🚀🔄
+
+## 🤔 What’s the Problem?
+When training a neural network, the activations (outputs) can vary a lot, making learning **slower** and **unstable**. 😖
+Batch Normalization **fixes this** by:
+✅ Making activations more consistent
+✅ Helping the network learn faster
+✅ Reducing problems like vanishing gradients
+
+---
+
+## 🔄 How Does Batch Normalization Work?
+
+### 🏗 Step 1: Normalize Each Mini-Batch
+For each neuron in a layer:
+1️⃣ Compute the **mean** and **standard deviation** of its activations. 📊
+2️⃣ Normalize the outputs using:
+ \[
+ z' = \frac{z - \text{mean}}{\text{std dev} + \epsilon}
+ \]
+ (We add a **small** value `ε` to avoid division by zero.)
+
+### 🏗 Step 2: Scale and Shift
+- Instead of leaving activations at 0 and 1, we **scale** and **shift** them:
+ \[
+ z'' = \gamma \cdot z' + \beta
+ \]
+- **γ (scale) and β (shift)** are **learned** during training! 🏋️♂️
+
+---
+
+## 🔬 Example: Normalizing Activations
+
+- **First Mini-Batch (X1)** ➝ Compute mean & std for each neuron, normalize, then scale & shift
+- **Second Mini-Batch (X2)** ➝ Repeat for new batch! ♻
+- **Next Layer** ➝ Apply batch normalization again! 🔄
+
+### 🏆 Prediction Time
+- During **training**, we compute the mean & std for **each batch**.
+- During **testing**, we use the **population mean & std** instead. 📊
+
+---
+
+## 🛠 Using Batch Normalization in PyTorch
+
+```python
+import torch.nn as nn
+
+class NeuralNetwork(nn.Module):
+ def __init__(self):
+ super(NeuralNetwork, self).__init__()
+ self.fc1 = nn.Linear(10, 3) # First layer (10 inputs, 3 neurons)
+ self.bn1 = nn.BatchNorm1d(3) # Batch Norm for first layer
+ self.fc2 = nn.Linear(3, 4) # Second layer (3 inputs, 4 neurons)
+ self.bn2 = nn.BatchNorm1d(4) # Batch Norm for second layer
+
+ def forward(self, x):
+ x = self.bn1(self.fc1(x)) # Apply Batch Norm
+ x = self.bn2(self.fc2(x)) # Apply Batch Norm again
+ return x
+```
+
+- **Training?** Set the model to **train mode** 🏋️♂️
+ ```python
+ model.train()
+ ```
+- **Predicting?** Use **evaluation mode** 📈
+ ```python
+ model.eval()
+ ```
+
+---
+
+## 🚀 Why Does Batch Normalization Work?
+
+### ✅ Helps Gradient Descent Work Better
+- Normalized data = **smoother** loss function 🎯
+- Gradients point in the **right** direction = Faster learning! 🚀
+
+### ✅ Reduces Vanishing Gradient Problem
+- Sigmoid & Tanh activations suffer from small gradients 😢
+- Normalization **keeps activations in a good range** 📊
+
+### ✅ Allows Higher Learning Rates
+- Networks can **train faster** without getting unstable ⏩
+
+### ✅ Reduces Need for Dropout
+- Some studies show **Batch Norm can replace Dropout** 🤯
+
+---
+
+🎉 **Great job!** Now, let’s try batch normalization in our own models! 🏗️📈
diff --git a/deep_networks.py b/deep_networks.py
new file mode 100644
index 0000000000000000000000000000000000000000..bd650d83cc47db5b267e9b4424639e8d435ed232
--- /dev/null
+++ b/deep_networks.py
@@ -0,0 +1,80 @@
+import torch
+import torch.nn as nn
+import torch.optim as optim
+import matplotlib.pyplot as plt
+import numpy as np
+
+# 🔥 Deep Neural Network Model
+class DeepNeuralNetwork(nn.Module):
+ def __init__(self, input_size, hidden_sizes, output_size):
+ super(DeepNeuralNetwork, self).__init__()
+ layers = []
+ in_size = input_size
+
+ for hidden_size in hidden_sizes:
+ layers.append(nn.Linear(in_size, hidden_size))
+ layers.append(nn.ReLU())
+ in_size = hidden_size
+
+ layers.append(nn.Linear(in_size, output_size))
+ self.model = nn.Sequential(*layers)
+
+ def forward(self, x):
+ return self.model(x) # ✅ Apply the model layers properly
+
+
+# 🔥 Training Function
+def train_model(model, criterion, optimizer, x_train, y_train, epochs=100):
+ model.train()
+ for epoch in range(epochs):
+ optimizer.zero_grad()
+
+ # Forward pass
+ y_pred = model(x_train)
+
+ # Loss calculation
+ loss = criterion(y_pred, y_train)
+
+ # Backward pass
+ loss.backward()
+ optimizer.step()
+
+ if (epoch + 1) % 10 == 0:
+ print(f'Epoch [{epoch + 1}/{epochs}], Loss: {loss.item():.4f}')
+
+
+# ✅ Example Usage
+if __name__ == "__main__":
+ # 🔥 Sample Data
+ x_train = torch.randn(100, 10, requires_grad=True) # ✅ Require gradient tracking
+ y_train = torch.randint(0, 2, (100,), dtype=torch.long) # ✅ Ensure LongTensor for CrossEntropyLoss
+
+ # Plotting the input data
+ plt.scatter(x_train[:, 0].detach().numpy(), x_train[:, 1].detach().numpy(), c=y_train.numpy(), cmap='viridis')
+ plt.title('Deep Neural Network Input Data')
+ plt.xlabel('Input Feature 1')
+ plt.ylabel('Input Feature 2')
+ plt.colorbar(label='Output Class')
+ plt.show()
+
+ # Initialize Model
+ model = DeepNeuralNetwork(input_size=10, hidden_sizes=[20, 10], output_size=2)
+
+ # Criterion and Optimizer
+ criterion = nn.CrossEntropyLoss()
+ optimizer = optim.SGD(model.parameters(), lr=0.01)
+
+ # Train the model
+ train_model(model, criterion, optimizer, x_train, y_train, epochs=100)
+
+ # ✅ Plotting the predictions with softmax
+ model.eval()
+ with torch.no_grad():
+ y_pred = torch.softmax(model(x_train), dim=1).detach().numpy()
+
+ plt.scatter(x_train[:, 0].detach().numpy(), x_train[:, 1].detach().numpy(), c=np.argmax(y_pred, axis=1), cmap='viridis')
+ plt.title('Deep Neural Network Predictions')
+ plt.xlabel('Input Feature 1')
+ plt.ylabel('Input Feature 2')
+ plt.colorbar(label='Predicted Class')
+ plt.show()
diff --git a/final_project.md b/final_project.md
new file mode 100644
index 0000000000000000000000000000000000000000..a4cd81ba35d53a9860ffff910b28c05901b852d0
--- /dev/null
+++ b/final_project.md
@@ -0,0 +1,29 @@
+# 🧠 **Simple Summary of the Program**
+
+1. **Loads and Prepares Data:**
+ - Uses the **MNIST dataset**, which contains images of handwritten digits (0-9).
+ - Resizes the images and converts them to tensors.
+ - Creates a **data loader** to batch the images and shuffle them for training.
+
+2. **Defines a CNN Model:**
+ - The **FinalCNN** model processes the images through layers:
+ - **Conv1:** Finds simple features like edges.
+ - **Pool1:** Reduces the size to focus on important features.
+ - **Conv2:** Finds more complex patterns.
+ - **Pool2:** Reduces the size again.
+ - **Flattening:** Converts the features into a single line of numbers.
+ - **Fully Connected Layers:** Makes predictions about what digit is in the image.
+
+3. **Trains the Model:**
+ - Uses the **Cross-Entropy Loss** to measure how far the predictions are from the real digit labels.
+ - Uses **Stochastic Gradient Descent (SGD)** to adjust the model parameters and make better predictions.
+ - Runs the training for **32 epochs**, slowly improving the accuracy.
+
+4. **Displays Predictions:**
+ - Shows **6 sample images** with the model's predictions and the actual labels.
+ - Prints the accuracy and loss for each epoch.
+
+5. **GPU Acceleration:**
+ - Uses **CUDA** if available, making the training faster by running on the GPU.
+
+✅ This program is like a smart detective that learns to recognize handwritten numbers by studying lots of examples and gradually improving its guesses.
diff --git a/final_project.py b/final_project.py
new file mode 100644
index 0000000000000000000000000000000000000000..69a16fa5606b23f49f66b5c9631a252772d12813
--- /dev/null
+++ b/final_project.py
@@ -0,0 +1,260 @@
+import torch
+import torch.nn as nn
+import torch.optim as optim
+from torchvision import datasets, transforms
+from torch.utils.data import DataLoader
+import matplotlib.pyplot as plt
+from tqdm import tqdm
+from dataset_loader import CustomMNISTDataset
+import os
+import matplotlib.font_manager as fm
+# CNN Model
+# CNN Model with output layer for 62 categories
+class FinalCNN(nn.Module):
+ def __init__(self):
+ super(FinalCNN, self).__init__()
+ self.conv1 = nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=0)
+ self.conv2 = nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=0)
+ self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
+ self.fc1 = nn.Linear(32 * 4 * 4, 120)
+ self.fc2 = nn.Linear(120, 84)
+ self.fc3 = nn.Linear(84, 62) # Output layer with 62 units for (0-9, a-z, A-Z)
+
+ def forward(self, x):
+ x = torch.relu(self.conv1(x))
+ x = self.pool(x)
+ x = torch.relu(self.conv2(x))
+ x = self.pool(x)
+ x = x.view(-1, 32 * 4 * 4)
+ x = torch.relu(self.fc1(x))
+ x = torch.relu(self.fc2(x))
+ x = self.fc3(x) # Final output
+ return x
+def plot_loss_accuracy(losses, accuracies):
+ """Plots Loss vs Accuracy on the same graph."""
+ plt.figure(figsize=(10, 6))
+
+ # Plot Loss
+ plt.plot(losses, color='red', label='Loss (Cost)', linestyle='-', marker='o')
+
+ # Plot Accuracy
+ plt.plot(accuracies, color='blue', label='Accuracy', linestyle='-', marker='x')
+
+ plt.title('Training Loss and Accuracy', fontsize=14)
+ plt.xlabel('Epochs', fontsize=12)
+ plt.ylabel('Value', fontsize=12)
+ plt.legend(loc='best')
+ plt.grid(True)
+
+ # Show the plot
+ plt.savefig("plot.svg")
+
+# 🔥 Function to choose the dataset dynamically
+def choose_dataset(dataset_name):
+ """Choose and load a custom dataset dynamically."""
+
+ # ✅ Dynamic path generation
+ base_path = './data'
+ dataset_path = os.path.join(base_path, dataset_name, 'raw')
+
+ # Validate dataset path
+ if not os.path.exists(dataset_path):
+ raise ValueError(f"❌ Dataset {dataset_name} not found at {dataset_path}")
+
+ # ✅ Locate image and label files dynamically
+ image_file = None
+ label_file = None
+
+ for file in os.listdir(dataset_path):
+ if 'images' in file:
+ image_file = os.path.join(dataset_path, file)
+ elif 'labels' in file:
+ label_file = os.path.join(dataset_path, file)
+
+ # Ensure both image and label files are found
+ if not image_file or not label_file:
+ raise ValueError(f"❌ Missing image or label files in {dataset_path}")
+
+ transform = transforms.Compose([
+ transforms.ToTensor(),
+ transforms.Normalize((0.5,), (0.5,)) # Normalize between -1 and 1
+ ])
+
+ # ✅ Load the custom dataset with file paths
+ dataset = CustomMNISTDataset(dataset_path=dataset_path, transform=transform)
+
+ return dataset
+
+
+# Print activation details once
+def print_activation_details(model, sample_batch):
+ """Print activation map sizes once before training."""
+ with torch.no_grad():
+ x = sample_batch
+ print("\n--- CNN Activation Details (One-time) ---")
+
+ x = model.conv1(x)
+ print(f"Conv1: {x.shape}")
+
+ x = model.pool(x)
+ print(f"Pool1: {x.shape}")
+
+ x = model.conv2(x)
+ print(f"Conv2: {x.shape}")
+
+ x = model.pool(x)
+ print(f"Pool2: {x.shape}")
+
+ x = x.view(-1, 32 * 4 * 4)
+ print(f"Flattened: {x.shape}")
+
+ x = model.fc1(x)
+ print(f"FC1: {x.shape}")
+
+ x = model.fc2(x)
+ print(f"FC2: {x.shape}")
+
+ x = model.fc3(x)
+ print(f"Output (Logits): {x.shape}\n")
+
+
+# Training Function
+def train_final_model(model, criterion, optimizer, train_loader, epochs=256):
+ losses = []
+ accuracies = []
+
+ # Print activation details once before training
+ sample_batch, _ = next(iter(train_loader))
+ print_activation_details(model, sample_batch)
+
+ model.train()
+
+ for epoch in range(epochs):
+ epoch_loss = 0.0
+ correct, total = 0, 0
+
+ # tqdm progress bar
+ with tqdm(train_loader, desc=f'Epoch {epoch + 1}/{epochs}', unit='batch') as t:
+ for images, labels in t:
+ optimizer.zero_grad()
+ outputs = model(images)
+ loss = criterion(outputs, labels)
+ loss.backward()
+ optimizer.step()
+
+ # Update metrics
+ epoch_loss += loss.item()
+ _, predicted = torch.max(outputs, 1)
+ total += labels.size(0)
+ correct += (predicted == labels).sum().item()
+
+ t.set_postfix(loss=loss.item())
+
+ # Store epoch loss and accuracy
+ losses.append(epoch_loss / len(train_loader))
+ accuracy = 100 * correct / total
+ accuracies.append(accuracy)
+
+ print(f"Epoch [{epoch+1}/{epochs}], Loss: {epoch_loss / len(train_loader):.4f}, Accuracy: {accuracy:.2f}%")
+
+ # After training, plot the loss and accuracy
+ plot_loss_accuracy(losses, accuracies)
+
+ return losses, accuracies
+
+
+# Display sample predictions
+
+def get_dataset_options(base_path='./data'):
+ """List all subdirectories in the data directory."""
+ try:
+ # List all subdirectories in the base_path (data folder)
+ options = [folder for folder in os.listdir(base_path) if os.path.isdir(os.path.join(base_path, folder))]
+ return options
+ except FileNotFoundError:
+ print(f"❌ Directory {base_path} not found!")
+ return []
+
+def number_to_char(number):
+ if 0 <= number <= 9:
+ return str(number) # 0-9
+ elif 10 <= number <= 35:
+ return chr(number + 87) # a-z (10 -> 'a', 35 -> 'z')
+ elif 36 <= number <= 61:
+ return chr(number + 65) # A-Z (36 -> 'A', 61 -> 'Z')
+ else:
+ return ''
+
+
+def display_predictions(model, data_loader, output_name, num_samples=6, font_path='./Daemon.otf'):
+ """Displays sample images with predicted labels"""
+ model.eval()
+
+ # Load custom font
+ prop = fm.FontProperties(fname=font_path)
+
+ images, labels = next(iter(data_loader))
+ with torch.no_grad():
+ outputs = model(images)
+ _, predictions = torch.max(outputs, 1)
+
+ # Displaying 6 samples
+ plt.figure(figsize=(12, 6))
+
+ for i in range(num_samples):
+ plt.subplot(2, 3, i + 1)
+ plt.imshow(images[i].squeeze(), cmap='gray')
+
+ # Convert predicted number to corresponding character
+ predicted_char = number_to_char(predictions[i].item())
+ actual_char = number_to_char(labels[i].item())
+
+ # Title with 'Predicted' and 'Actual' both in custom font
+ if(predicted_char == actual_char):
+ plt.title(f'{predicted_char} = {actual_char}', fontsize=84, fontproperties=prop)
+ else:
+ plt.title(f'{predicted_char} != {actual_char}', fontsize=84, fontproperties=prop)
+
+ plt.axis('off')
+
+ plt.savefig(output_name)
+
+
+if __name__ == "__main__":
+ # Choose Dataset
+ dataset_options = get_dataset_options()
+
+ if dataset_options:
+ # Dynamically display dataset options
+ print("Available datasets:")
+ for i, option in enumerate(dataset_options, 1):
+ print(f"{i}. {option}")
+
+ # User input to choose a dataset
+ dataset_index = int(input(f"Enter the number corresponding to the dataset (1-{len(dataset_options)}): ")) - 1
+
+ # Ensure valid selection
+ if 0 <= dataset_index < len(dataset_options):
+ dataset_name = dataset_options[dataset_index]
+ print(f"You selected: {dataset_name}")
+ else:
+ print("❌ Invalid selection.")
+ dataset_name = None
+ else:
+ print("❌ No datasets found in the data folder.")
+ dataset_name = None
+
+ train_dataset = choose_dataset(dataset_name)
+ train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
+
+ # Model, Criterion, and Optimizer
+ model = FinalCNN()
+ criterion = nn.CrossEntropyLoss()
+ optimizer = optim.SGD(model.parameters(), lr=0.005)
+
+ display_predictions(model, train_loader, output_name="before.svg")
+ # Train the Model
+ losses, accuracies = train_final_model(model, criterion, optimizer, train_loader, epochs=256)
+
+ # Display sample predictions
+ display_predictions(model, train_loader, output_name="after.svg")
diff --git a/font.py b/font.py
new file mode 100644
index 0000000000000000000000000000000000000000..0ed91be32bcf51608ed48af8245806f74ceddace
--- /dev/null
+++ b/font.py
@@ -0,0 +1,138 @@
+import os
+import struct
+import numpy as np
+import torch
+import gzip
+from PIL import Image, ImageFont, ImageDraw
+import cv2
+import random
+import string
+
+# 📝 Define the HandwrittenFontDataset class
+class HandwrittenFontDataset(torch.utils.data.Dataset):
+ def __init__(self, font_path, num_samples):
+ self.font_path = font_path
+ self.num_samples = num_samples
+ self.font = ImageFont.truetype(self.font_path, 32) # Font size
+ self.characters = string.digits + string.ascii_uppercase + string.ascii_lowercase
+
+ def __len__(self):
+ return self.num_samples
+
+ def __getitem__(self, index):
+ # Randomly choose a character
+ char = random.choice(self.characters)
+ # Proceed with image creation and processing...
+
+ # Create image with that character
+ img = Image.new('L', (64, 64), color=255) # Create a blank image (grayscale)
+ draw = ImageDraw.Draw(img)
+ draw.text((10, 10), char, font=self.font, fill=0) # Draw the character
+
+ # Convert image to numpy array (resize to 28x28 for MNIST format)
+ img = np.array(img)
+ img = preprocess_for_mnist(img)
+
+ # Convert character to label (integer)
+ label = self.characters.index(char)
+
+ return torch.tensor(img, dtype=torch.uint8), label
+
+# 📄 Resize and preprocess images for MNIST format
+def preprocess_for_mnist(img):
+ """Resize image to 28x28 and normalize to 0-255 range."""
+ img = cv2.resize(img, (28, 28), interpolation=cv2.INTER_AREA)
+ img = img.astype(np.uint8) # Convert to unsigned byte
+ return img
+
+# 📄 Write images to idx3-ubyte format
+def write_idx3_ubyte(images, file_path):
+ """Write images to idx3-ubyte format."""
+ with open(file_path, 'wb') as f:
+ # Magic number (0x00000801 for image files)
+ f.write(struct.pack(">IIII", 2051, len(images), 28, 28))
+
+ # Write image data as unsigned bytes (each pixel in range [0, 255])
+ for image in images:
+ f.write(image.tobytes())
+
+# 📄 Write labels to idx1-ubyte format
+def write_idx1_ubyte(labels, file_path):
+ """Write labels to idx1-ubyte format."""
+ with open(file_path, 'wb') as f:
+ # Magic number (0x00000801 for label files)
+ f.write(struct.pack(">II", 2049, len(labels)))
+
+ # Write each label as a byte
+ for label in labels:
+ f.write(struct.pack("B", label))
+
+# 📄 Compress file to .gz format
+def compress_file(input_path, output_path):
+ """Compress the idx3 and idx1 files to .gz format."""
+ with open(input_path, 'rb') as f_in:
+ with gzip.open(output_path, 'wb') as f_out:
+ f_out.writelines(f_in)
+
+# 📊 Save dataset in MNIST format
+def save_mnist_format(images, labels, output_dir):
+ """Save the dataset in MNIST format to raw/ directory."""
+ raw_dir = os.path.join(output_dir, "raw")
+ os.makedirs(raw_dir, exist_ok=True)
+
+ # Prepare file paths
+ train_images_path = os.path.join(raw_dir, "train-images-idx3-ubyte")
+ train_labels_path = os.path.join(raw_dir, "train-labels-idx1-ubyte")
+
+ # Write uncompressed idx3 and idx1 files
+ write_idx3_ubyte(images, train_images_path)
+ write_idx1_ubyte(labels, train_labels_path)
+
+ # Compress idx3 and idx1 files into .gz format
+ compress_file(train_images_path, f"{train_images_path}.gz")
+ compress_file(train_labels_path, f"{train_labels_path}.gz")
+
+ print(f"Dataset saved in MNIST format at {raw_dir}")
+
+# ✅ Generate and save the dataset
+def create_mnist_dataset(font_path, num_samples=4096):
+ """Generate dataset and save in MNIST format."""
+ # Get font name without extension
+ font_name = os.path.splitext(os.path.basename(font_path))[0]
+ output_dir = os.path.join("./data", font_name)
+
+ # Ensure the directory exists
+ os.makedirs(output_dir, exist_ok=True)
+
+ dataset = HandwrittenFontDataset(font_path, num_samples)
+
+ images = []
+ labels = []
+
+ for i in range(num_samples):
+ img, label = dataset[i]
+ images.append(img.numpy())
+ labels.append(label)
+
+ # Save in MNIST format
+ save_mnist_format(images, labels, output_dir)
+
+# 🔥 Example usage
+def choose_font_and_create_dataset():
+ # List all TTF and OTF files in the root directory
+ font_files = [f for f in os.listdir("./") if f.endswith(".ttf") or f.endswith(".otf")]
+
+ # Display available fonts for user to choose
+ print("Available fonts:")
+ for i, font_file in enumerate(font_files):
+ print(f"{i+1}. {font_file}")
+
+ # Get user's choice
+ choice = int(input(f"Choose a font (1-{len(font_files)}): "))
+ chosen_font = font_files[choice - 1]
+
+ print(f"Creating dataset using font: {chosen_font}")
+ create_mnist_dataset(chosen_font)
+
+# Run the font selection and dataset creation
+choose_font_and_create_dataset()
diff --git a/install.bat b/install.bat
new file mode 100644
index 0000000000000000000000000000000000000000..b32d513498d018142f528d799031c96e27b69eda
--- /dev/null
+++ b/install.bat
@@ -0,0 +1,7 @@
+@echo off
+REM Create a virtual environment
+python -m venv .pytorchenv
+REM Activate the virtual environment
+call .pytorchenv\Scripts\activate
+REM Install required Python packages
+pip install -r requirements.txt
diff --git a/install.sh b/install.sh
new file mode 100644
index 0000000000000000000000000000000000000000..990f198c0138bbc11cd10b0f137fbcd62ae89db5
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+# Create a virtual environment
+python -m venv .pytorchenv
+# Activate the virtual environment
+source .pytorchenv/bin/activate
+# Install required Python packages
+pip install -r requirements.txt
diff --git a/logistic_regression.py b/logistic_regression.py
new file mode 100644
index 0000000000000000000000000000000000000000..c462771c965221715f33bc4066edf56f8cdc8c0a
--- /dev/null
+++ b/logistic_regression.py
@@ -0,0 +1,65 @@
+import torch
+import torch.nn as nn
+import torch.optim as optim
+import numpy as np
+from torch.utils.data import DataLoader, TensorDataset
+
+
+# Logistic Regression Model
+class LogisticRegressionModel(nn.Module):
+ def __init__(self, input_size):
+ super(LogisticRegressionModel, self).__init__()
+ self.linear = nn.Linear(input_size, 1)
+
+ def forward(self, x):
+ return torch.sigmoid(self.linear(x))
+
+# Cross-Entropy Loss Function
+def cross_entropy_loss(y_pred, y_true):
+ return -torch.mean(y_true * torch.log(y_pred) + (1 - y_true) * torch.log(1 - y_pred))
+
+# Training Function
+def train_model(model, criterion, optimizer, x_train, y_train, epochs=100):
+ print("Initial model parameters:", list(model.parameters()))
+ for epoch in range(epochs):
+ print(f'Epoch {epoch+1}/{epochs}')
+
+ model.train()
+ optimizer.zero_grad()
+ y_pred = model(x_train)
+ loss = criterion(y_pred, y_train)
+ loss.backward()
+ optimizer.step()
+ # Removed cross_entropy calculation as it is redundant
+
+
+
+
+ print(f'Loss: {loss.item():.4f}, Learning Rate: {optimizer.param_groups[0]["lr"]}')
+
+ if (epoch+1) % 10 == 0:
+
+ print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}')
+
+# Example Usage
+if __name__ == "__main__":
+ # Sample Data
+ x_data = torch.tensor(np.random.rand(100, 2), dtype=torch.float32)
+ y_data = torch.tensor(np.random.randint(0, 2, (100, 1)), dtype=torch.float32)
+
+ # Create Dataset and DataLoader
+ dataset = TensorDataset(x_data, y_data)
+ train_loader = DataLoader(dataset, batch_size=10, shuffle=True)
+
+ model = LogisticRegressionModel(input_size=2)
+
+ # Initialize criterion and optimizer
+ criterion = nn.BCELoss()
+ optimizer = optim.SGD(model.parameters(), lr=0.01)
+
+ # Call the training function
+ train_model(model, criterion, optimizer, x_data, y_data, epochs=100)
+
+ with torch.no_grad():
+ sample_predictions = model(x_data)
+ print("Sample predictions after training:", sample_predictions)
diff --git a/metrics.png b/metrics.png
new file mode 100644
index 0000000000000000000000000000000000000000..a85caa6c1653c8df9d067bceb1fbb05122bfd554
Binary files /dev/null and b/metrics.png differ
diff --git a/metrics.svg b/metrics.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f46408ead666a7e952c50a4725e0770301aff08f
--- /dev/null
+++ b/metrics.svg
@@ -0,0 +1,1313 @@
+
+
+
diff --git a/plot.png b/plot.png
new file mode 100644
index 0000000000000000000000000000000000000000..bf5c4eda11cf6925bf00df5a7c15efe0dbde7fd3
Binary files /dev/null and b/plot.png differ
diff --git a/plot.svg b/plot.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f1c13708b3beb83d620291eb5d736260f67f481b
--- /dev/null
+++ b/plot.svg
@@ -0,0 +1,1431 @@
+
+
+
diff --git a/predictions.svg b/predictions.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e8c6f7dffc4460c390e25a89313118158efdfe95
--- /dev/null
+++ b/predictions.svg
@@ -0,0 +1,309 @@
+
+
+
diff --git a/readme.txt b/readme.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b2911a10f376416f5bbbf7761369f0f4b2dccb80
--- /dev/null
+++ b/readme.txt
@@ -0,0 +1 @@
+enak banget gratis yah cox hahahahha
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b594fb4f17be168c0ae5b17662cbeb61ce255ec2
Binary files /dev/null and b/requirements.txt differ
diff --git a/shallow_neural_network.py b/shallow_neural_network.py
new file mode 100644
index 0000000000000000000000000000000000000000..188b26b8bfd54cf06256d9dd34fc0899711d988e
--- /dev/null
+++ b/shallow_neural_network.py
@@ -0,0 +1,59 @@
+import torch
+import torch.nn as nn
+import torch.optim as optim
+
+# Shallow Neural Network Model
+class ShallowNeuralNetwork(nn.Module):
+ def __init__(self, input_size, hidden_size, output_size):
+ super(ShallowNeuralNetwork, self).__init__()
+ self.hidden = nn.Linear(input_size, hidden_size)
+ self.output = nn.Linear(hidden_size, output_size)
+
+ def forward(self, x):
+ x = torch.relu(self.hidden(x))
+ return self.output(x)
+
+# Training Function
+def train_model(model, criterion, optimizer, x_train, y_train, epochs=100):
+ for epoch in range(epochs):
+ model.train()
+ optimizer.zero_grad()
+ y_pred = model(x_train)
+ loss = criterion(y_pred, y_train)
+ loss.backward()
+ optimizer.step()
+ if (epoch+1) % 10 == 0:
+ print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}')
+
+import matplotlib.pyplot as plt # Added import for plotting
+
+# Example Usage
+if __name__ == "__main__":
+ # Sample Data
+ x_train = torch.randn(100, 2)
+ y_train = torch.randint(0, 2, (100,))
+
+ # Plotting the input data
+ plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train.numpy(), cmap='viridis')
+ plt.title('Shallow Neural Network Input Data')
+ plt.xlabel('Input Feature 1')
+ plt.ylabel('Input Feature 2')
+ plt.colorbar(label='Output Class')
+ plt.show()
+
+
+ model = ShallowNeuralNetwork(input_size=2, hidden_size=5, output_size=2)
+
+ # Plotting the predictions
+ y_pred = model(x_train).detach().numpy()
+ plt.scatter(x_train[:, 0], x_train[:, 1], c=np.argmax(y_pred, axis=1), cmap='viridis')
+ plt.title('Shallow Neural Network Predictions')
+ plt.xlabel('Input Feature 1')
+ plt.ylabel('Input Feature 2')
+ plt.colorbar(label='Predicted Class')
+ plt.show()
+
+ criterion = nn.CrossEntropyLoss()
+ optimizer = optim.SGD(model.parameters(), lr=0.01)
+
+ train_model(model, criterion, optimizer, x_train, y_train)
diff --git a/softmax_regression.py b/softmax_regression.py
new file mode 100644
index 0000000000000000000000000000000000000000..123145919436d73eeb781ed06f75e04cd06c443b
--- /dev/null
+++ b/softmax_regression.py
@@ -0,0 +1,57 @@
+import torch
+import torch.nn as nn
+import torch.optim as optim
+
+# Softmax Regression Model
+class SoftmaxRegressionModel(nn.Module):
+ def __init__(self, input_size, num_classes):
+ super(SoftmaxRegressionModel, self).__init__()
+ self.linear = nn.Linear(input_size, num_classes)
+
+ def forward(self, x):
+ return torch.softmax(self.linear(x), dim=1)
+
+# Training Function
+def train_model(model, criterion, optimizer, x_train, y_train, epochs=100):
+ for epoch in range(epochs):
+ model.train()
+ optimizer.zero_grad()
+ y_pred = model(x_train)
+ loss = criterion(y_pred, y_train)
+ loss.backward()
+ optimizer.step()
+ if (epoch+1) % 10 == 0:
+ print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}')
+
+import matplotlib.pyplot as plt # Added import for plotting
+
+# Example Usage
+if __name__ == "__main__":
+ # Sample Data
+ x_train = torch.randn(100, 2)
+ y_train = torch.randint(0, 2, (100,))
+
+ # Plotting the input data
+ plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train.numpy(), cmap='viridis')
+ plt.title('Softmax Regression Input Data')
+ plt.xlabel('Input Feature 1')
+ plt.ylabel('Input Feature 2')
+ plt.colorbar(label='Output Class')
+ plt.show()
+
+
+ model = SoftmaxRegressionModel(input_size=2, num_classes=2)
+
+ # Plotting the predictions
+ y_pred = model(x_train).detach().numpy()
+ plt.scatter(x_train[:, 0], x_train[:, 1], c=np.argmax(y_pred, axis=1), cmap='viridis')
+ plt.title('Softmax Regression Predictions')
+ plt.xlabel('Input Feature 1')
+ plt.ylabel('Input Feature 2')
+ plt.colorbar(label='Predicted Class')
+ plt.show()
+
+ criterion = nn.CrossEntropyLoss()
+ optimizer = optim.SGD(model.parameters(), lr=0.01)
+
+ train_model(model, criterion, optimizer, x_train, y_train)
diff --git a/space age.ttf b/space age.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..85a62a8f684c523987a049cef3ffd5f8a39ab1d4
Binary files /dev/null and b/space age.ttf differ
diff --git a/start.bat b/start.bat
new file mode 100644
index 0000000000000000000000000000000000000000..a2a0a6ace183a119d973665592565d786b0a3efa
--- /dev/null
+++ b/start.bat
@@ -0,0 +1,5 @@
+@echo off
+REM Activate the virtual environment
+call .pytorchenv\Scripts\activate
+REM Run the main application
+python main.py
diff --git a/start.sh b/start.sh
new file mode 100644
index 0000000000000000000000000000000000000000..0d1593a040d36ab9f15ac5c336615911328f8dbe
--- /dev/null
+++ b/start.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# Activate the virtual environment
+source .pytorchenv/bin/activate
+# Run the main application
+python main.py
diff --git a/svg_name.svg b/svg_name.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c8f5bdf01609a099e457219faa2d7a33a683e1a3
--- /dev/null
+++ b/svg_name.svg
@@ -0,0 +1 @@
+\n\n