TensorFlow.org এ দেখুন | Google Colab-এ চালান | GitHub-এ উৎস দেখুন | নোটবুক ডাউনলোড করুন |
ফিচারাইজেশন টিউটোরিয়ালে আমরা আমাদের মডেলগুলিতে শুধুমাত্র ব্যবহারকারী এবং মুভি শনাক্তকারীর বাইরে একাধিক বৈশিষ্ট্য অন্তর্ভুক্ত করেছি, কিন্তু সেই বৈশিষ্ট্যগুলি মডেলের নির্ভুলতা উন্নত করে কিনা তা আমরা অন্বেষণ করিনি।
আইডির বাইরের বৈশিষ্ট্যগুলি সুপারিশকারী মডেলে উপযোগী কিনা তা অনেক কারণ প্রভাবিত করে:
- প্রসঙ্গের গুরুত্ব : যদি ব্যবহারকারীর পছন্দগুলি প্রসঙ্গ এবং সময় জুড়ে তুলনামূলকভাবে স্থিতিশীল থাকে, তবে প্রসঙ্গ বৈশিষ্ট্যগুলি খুব বেশি সুবিধা প্রদান করতে পারে না। যাইহোক, ব্যবহারকারীদের পছন্দগুলি অত্যন্ত প্রাসঙ্গিক হলে, প্রসঙ্গ যোগ করা মডেলটিকে উল্লেখযোগ্যভাবে উন্নত করবে। উদাহরণস্বরূপ, একটি সংক্ষিপ্ত ক্লিপ বা একটি চলচ্চিত্র সুপারিশ করার সিদ্ধান্ত নেওয়ার সময় সপ্তাহের দিনটি একটি গুরুত্বপূর্ণ বৈশিষ্ট্য হতে পারে: ব্যবহারকারীরা সপ্তাহে শুধুমাত্র ছোট বিষয়বস্তু দেখার জন্য সময় থাকতে পারে, তবে সপ্তাহান্তে একটি পূর্ণ-দৈর্ঘ্যের চলচ্চিত্রটি আরাম করতে এবং উপভোগ করতে পারে . একইভাবে, কোয়েরি টাইমস্ট্যাম্পগুলি জনপ্রিয়তার গতিশীলতার মডেলিংয়ে একটি গুরুত্বপূর্ণ ভূমিকা পালন করতে পারে: একটি চলচ্চিত্র তার মুক্তির সময় খুব জনপ্রিয় হতে পারে, কিন্তু পরে দ্রুত ক্ষয়প্রাপ্ত হয়। বিপরীতভাবে, অন্যান্য চলচ্চিত্রগুলি চিরসবুজ হতে পারে যা আনন্দের সাথে বারবার দেখা হয়।
- ডেটা স্পারসিটি : ডেটা স্পারস হলে অ-আইডি বৈশিষ্ট্যগুলি ব্যবহার করা গুরুত্বপূর্ণ হতে পারে। একটি প্রদত্ত ব্যবহারকারী বা আইটেমের জন্য উপলব্ধ কয়েকটি পর্যবেক্ষণের সাথে, মডেলটি প্রতি-ব্যবহারকারী বা প্রতি-আইটেম প্রতিনিধিত্বের জন্য একটি ভাল অনুমান করার সাথে সংগ্রাম করতে পারে। একটি সঠিক মডেল তৈরি করতে, অন্যান্য বৈশিষ্ট্য যেমন আইটেম বিভাগ, বর্ণনা এবং চিত্রগুলিকে প্রশিক্ষণের ডেটার বাইরে মডেলটিকে সাধারণীকরণে সহায়তা করার জন্য ব্যবহার করতে হবে। এটি বিশেষত কোল্ড-স্টার্ট পরিস্থিতিতে প্রাসঙ্গিক, যেখানে কিছু আইটেম বা ব্যবহারকারীর উপর তুলনামূলকভাবে কম ডেটা পাওয়া যায়।
এই টিউটোরিয়ালে, আমরা আমাদের MovieLens মডেলে মুভির শিরোনাম এবং ব্যবহারকারী আইডি ছাড়াও বৈশিষ্ট্যগুলি ব্যবহার করে পরীক্ষা করব।
প্রাথমিক
আমরা প্রথমে প্রয়োজনীয় প্যাকেজ আমদানি করি।
pip install -q tensorflow-recommenders
pip install -q --upgrade tensorflow-datasets
import os
import tempfile
import numpy as np
import tensorflow as tf
import tensorflow_datasets as tfds
import tensorflow_recommenders as tfrs
আমরা ফিচারাইজেশন টিউটোরিয়াল অনুসরণ করি এবং ব্যবহারকারী আইডি, টাইমস্ট্যাম্প এবং চলচ্চিত্রের শিরোনামের বৈশিষ্ট্যগুলি রাখি।
ratings = tfds.load("movielens/100k-ratings", split="train")
movies = tfds.load("movielens/100k-movies", split="train")
ratings = ratings.map(lambda x: {
"movie_title": x["movie_title"],
"user_id": x["user_id"],
"timestamp": x["timestamp"],
})
movies = movies.map(lambda x: x["movie_title"])
আমরা বৈশিষ্ট্য শব্দভান্ডার প্রস্তুত করার জন্য কিছু হাউসকিপিং করি।
timestamps = np.concatenate(list(ratings.map(lambda x: x["timestamp"]).batch(100)))
max_timestamp = timestamps.max()
min_timestamp = timestamps.min()
timestamp_buckets = np.linspace(
min_timestamp, max_timestamp, num=1000,
)
unique_movie_titles = np.unique(np.concatenate(list(movies.batch(1000))))
unique_user_ids = np.unique(np.concatenate(list(ratings.batch(1_000).map(
lambda x: x["user_id"]))))
মডেল সংজ্ঞা
কোয়েরি মডেল
আমরা আমাদের মডেলের প্রথম স্তর হিসাবে ফিচারাইজেশন টিউটোরিয়ালে সংজ্ঞায়িত ব্যবহারকারী মডেল দিয়ে শুরু করি, কাঁচা ইনপুট উদাহরণগুলিকে বৈশিষ্ট্য এমবেডিংয়ে রূপান্তর করার দায়িত্ব দেওয়া হয়েছে৷ যাইহোক, টাইমস্ট্যাম্প বৈশিষ্ট্যগুলি চালু বা বন্ধ করার জন্য আমরা এটিকে সামান্য পরিবর্তন করি। এটি আমাদের মডেলের উপর টাইমস্ট্যাম্প বৈশিষ্ট্যগুলির প্রভাবকে আরও সহজে প্রদর্শন করার অনুমতি দেবে। নীচের কোডে, use_timestamps
প্যারামিটার আমাদের নিয়ন্ত্রণ করে যে আমরা টাইমস্ট্যাম্প বৈশিষ্ট্যগুলি ব্যবহার করি কিনা।
class UserModel(tf.keras.Model):
def __init__(self, use_timestamps):
super().__init__()
self._use_timestamps = use_timestamps
self.user_embedding = tf.keras.Sequential([
tf.keras.layers.StringLookup(
vocabulary=unique_user_ids, mask_token=None),
tf.keras.layers.Embedding(len(unique_user_ids) + 1, 32),
])
if use_timestamps:
self.timestamp_embedding = tf.keras.Sequential([
tf.keras.layers.Discretization(timestamp_buckets.tolist()),
tf.keras.layers.Embedding(len(timestamp_buckets) + 1, 32),
])
self.normalized_timestamp = tf.keras.layers.Normalization(
axis=None
)
self.normalized_timestamp.adapt(timestamps)
def call(self, inputs):
if not self._use_timestamps:
return self.user_embedding(inputs["user_id"])
return tf.concat([
self.user_embedding(inputs["user_id"]),
self.timestamp_embedding(inputs["timestamp"]),
tf.reshape(self.normalized_timestamp(inputs["timestamp"]), (-1, 1)),
], axis=1)
মনে রাখবেন যে এই টিউটোরিয়ালে টাইমস্ট্যাম্প বৈশিষ্ট্যগুলির ব্যবহার আমাদের প্রশিক্ষণ-পরীক্ষা বিভক্ত করার পছন্দের সাথে একটি অবাঞ্ছিত উপায়ে ইন্টারঅ্যাক্ট করে। কারণ আমরা আমাদের ডেটা কালানুক্রমিকভাবে না করে এলোমেলোভাবে বিভক্ত করেছি (নিশ্চিত করার জন্য যে পরীক্ষা ডেটাসেটের অন্তর্গত ঘটনাগুলি প্রশিক্ষণ সেটের চেয়ে পরে ঘটে), আমাদের মডেল কার্যকরভাবে ভবিষ্যতে থেকে শিখতে পারে। এটি অবাস্তব: সর্বোপরি, আমরা আগামীকাল থেকে ডেটাতে আজকে একটি মডেলকে প্রশিক্ষণ দিতে পারি না।
এর মানে হল যে মডেলটিতে সময়ের বৈশিষ্ট্যগুলি যোগ করার ফলে এটি ভবিষ্যতের মিথস্ক্রিয়া নিদর্শনগুলি শিখতে দেয়৷ আমরা এটি শুধুমাত্র দৃষ্টান্তের উদ্দেশ্যে করি: মুভিলেন্স ডেটাসেট নিজেই খুব ঘন, এবং অনেক বাস্তব-বিশ্বের ডেটাসেটের বিপরীতে ব্যবহারকারী আইডি এবং চলচ্চিত্রের শিরোনামের বাইরের বৈশিষ্ট্যগুলি থেকে খুব বেশি উপকৃত হয় না।
এই সতর্কতা বাদ দিয়ে, বাস্তব-বিশ্বের মডেলগুলি অন্যান্য সময়-ভিত্তিক বৈশিষ্ট্যগুলি যেমন দিনের সময় বা সপ্তাহের দিনগুলি থেকে ভালভাবে উপকৃত হতে পারে, বিশেষ করে যদি ডেটাতে শক্তিশালী মৌসুমী নিদর্শন থাকে।
প্রার্থী মডেল
সরলতার জন্য, আমরা প্রার্থীর মডেল ঠিক রাখব। আবার, আমরা ফিচারাইজেশন টিউটোরিয়াল থেকে এটি অনুলিপি করি:
class MovieModel(tf.keras.Model):
def __init__(self):
super().__init__()
max_tokens = 10_000
self.title_embedding = tf.keras.Sequential([
tf.keras.layers.StringLookup(
vocabulary=unique_movie_titles, mask_token=None),
tf.keras.layers.Embedding(len(unique_movie_titles) + 1, 32)
])
self.title_vectorizer = tf.keras.layers.TextVectorization(
max_tokens=max_tokens)
self.title_text_embedding = tf.keras.Sequential([
self.title_vectorizer,
tf.keras.layers.Embedding(max_tokens, 32, mask_zero=True),
tf.keras.layers.GlobalAveragePooling1D(),
])
self.title_vectorizer.adapt(movies)
def call(self, titles):
return tf.concat([
self.title_embedding(titles),
self.title_text_embedding(titles),
], axis=1)
সম্মিলিত মডেল
UserModel
এবং MovieModel
সংজ্ঞায়িত করে, আমরা একটি সম্মিলিত মডেল একসাথে রাখতে পারি এবং আমাদের ক্ষতি এবং মেট্রিক্স লজিক বাস্তবায়ন করতে পারি।
এখানে আমরা একটি পুনরুদ্ধার মডেল তৈরি করছি। এটি কীভাবে কাজ করে তার রিফ্রেশারের জন্য, বেসিক পুনরুদ্ধার টিউটোরিয়ালটি দেখুন।
নোট করুন যে আমাদের নিশ্চিত করতে হবে যে ক্যোয়ারী মডেল এবং প্রার্থী মডেল সামঞ্জস্যপূর্ণ আকারের আউটপুট এমবেডিং। যেহেতু আমরা আরও বৈশিষ্ট্য যোগ করে তাদের আকার পরিবর্তন করব, এটি সম্পন্ন করার সবচেয়ে সহজ উপায় হল প্রতিটি মডেলের পরে একটি ঘন প্রক্ষেপণ স্তর ব্যবহার করা:
class MovielensModel(tfrs.models.Model):
def __init__(self, use_timestamps):
super().__init__()
self.query_model = tf.keras.Sequential([
UserModel(use_timestamps),
tf.keras.layers.Dense(32)
])
self.candidate_model = tf.keras.Sequential([
MovieModel(),
tf.keras.layers.Dense(32)
])
self.task = tfrs.tasks.Retrieval(
metrics=tfrs.metrics.FactorizedTopK(
candidates=movies.batch(128).map(self.candidate_model),
),
)
def compute_loss(self, features, training=False):
# We only pass the user id and timestamp features into the query model. This
# is to ensure that the training inputs would have the same keys as the
# query inputs. Otherwise the discrepancy in input structure would cause an
# error when loading the query model after saving it.
query_embeddings = self.query_model({
"user_id": features["user_id"],
"timestamp": features["timestamp"],
})
movie_embeddings = self.candidate_model(features["movie_title"])
return self.task(query_embeddings, movie_embeddings)
পরীক্ষা-নিরীক্ষা
ডেটা প্রস্তুত করুন
আমরা প্রথমে একটি প্রশিক্ষণ সেট এবং একটি পরীক্ষার সেটে ডেটা বিভক্ত করি।
tf.random.set_seed(42)
shuffled = ratings.shuffle(100_000, seed=42, reshuffle_each_iteration=False)
train = shuffled.take(80_000)
test = shuffled.skip(80_000).take(20_000)
cached_train = train.shuffle(100_000).batch(2048)
cached_test = test.batch(4096).cache()
বেসলাইন: টাইমস্ট্যাম্প বৈশিষ্ট্য নেই
আমরা আমাদের প্রথম মডেলটি চেষ্টা করার জন্য প্রস্তুত: আসুন আমাদের বেসলাইন স্থাপন করতে টাইমস্ট্যাম্প বৈশিষ্ট্যগুলি ব্যবহার না করে শুরু করি।
model = MovielensModel(use_timestamps=False)
model.compile(optimizer=tf.keras.optimizers.Adagrad(0.1))
model.fit(cached_train, epochs=3)
train_accuracy = model.evaluate(
cached_train, return_dict=True)["factorized_top_k/top_100_categorical_accuracy"]
test_accuracy = model.evaluate(
cached_test, return_dict=True)["factorized_top_k/top_100_categorical_accuracy"]
print(f"Top-100 accuracy (train): {train_accuracy:.2f}.")
print(f"Top-100 accuracy (test): {test_accuracy:.2f}.")
Epoch 1/3 WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor. Received: inputs={'user_id': <tf.Tensor 'IteratorGetNext:2' shape=(None,) dtype=string>, 'timestamp': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=int64>}. Consider rewriting this model with the Functional API. WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor. Received: inputs={'user_id': <tf.Tensor 'IteratorGetNext:2' shape=(None,) dtype=string>, 'timestamp': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=int64>}. Consider rewriting this model with the Functional API. WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor. Received: inputs={'user_id': <tf.Tensor 'IteratorGetNext:2' shape=(None,) dtype=string>, 'timestamp': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=int64>}. Consider rewriting this model with the Functional API. WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor. Received: inputs={'user_id': <tf.Tensor 'IteratorGetNext:2' shape=(None,) dtype=string>, 'timestamp': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=int64>}. Consider rewriting this model with the Functional API. 40/40 [==============================] - 10s 169ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0092 - factorized_top_k/top_5_categorical_accuracy: 0.0172 - factorized_top_k/top_10_categorical_accuracy: 0.0256 - factorized_top_k/top_50_categorical_accuracy: 0.0824 - factorized_top_k/top_100_categorical_accuracy: 0.1473 - loss: 14579.4628 - regularization_loss: 0.0000e+00 - total_loss: 14579.4628 Epoch 2/3 40/40 [==============================] - 9s 173ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0020 - factorized_top_k/top_5_categorical_accuracy: 0.0126 - factorized_top_k/top_10_categorical_accuracy: 0.0251 - factorized_top_k/top_50_categorical_accuracy: 0.1129 - factorized_top_k/top_100_categorical_accuracy: 0.2133 - loss: 14136.2137 - regularization_loss: 0.0000e+00 - total_loss: 14136.2137 Epoch 3/3 40/40 [==============================] - 9s 174ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0021 - factorized_top_k/top_5_categorical_accuracy: 0.0155 - factorized_top_k/top_10_categorical_accuracy: 0.0307 - factorized_top_k/top_50_categorical_accuracy: 0.1389 - factorized_top_k/top_100_categorical_accuracy: 0.2535 - loss: 13939.9265 - regularization_loss: 0.0000e+00 - total_loss: 13939.9265 WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor. Received: inputs={'user_id': <tf.Tensor 'IteratorGetNext:2' shape=(None,) dtype=string>, 'timestamp': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=int64>}. Consider rewriting this model with the Functional API. WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor. Received: inputs={'user_id': <tf.Tensor 'IteratorGetNext:2' shape=(None,) dtype=string>, 'timestamp': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=int64>}. Consider rewriting this model with the Functional API. 40/40 [==============================] - 10s 189ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0036 - factorized_top_k/top_5_categorical_accuracy: 0.0226 - factorized_top_k/top_10_categorical_accuracy: 0.0427 - factorized_top_k/top_50_categorical_accuracy: 0.1729 - factorized_top_k/top_100_categorical_accuracy: 0.2944 - loss: 13711.3802 - regularization_loss: 0.0000e+00 - total_loss: 13711.3802 5/5 [==============================] - 3s 267ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0010 - factorized_top_k/top_5_categorical_accuracy: 0.0078 - factorized_top_k/top_10_categorical_accuracy: 0.0184 - factorized_top_k/top_50_categorical_accuracy: 0.1051 - factorized_top_k/top_100_categorical_accuracy: 0.2126 - loss: 30995.8988 - regularization_loss: 0.0000e+00 - total_loss: 30995.8988 Top-100 accuracy (train): 0.29. Top-100 accuracy (test): 0.21.
এটি আমাদের প্রায় 0.2 এর বেসলাইন শীর্ষ-100 নির্ভুলতা দেয়।
সময়ের বৈশিষ্ট্য সহ সময়ের গতিবিদ্যা ক্যাপচার করা
আমরা সময় বৈশিষ্ট্য যোগ যদি ফলাফল পরিবর্তন হয়?
model = MovielensModel(use_timestamps=True)
model.compile(optimizer=tf.keras.optimizers.Adagrad(0.1))
model.fit(cached_train, epochs=3)
train_accuracy = model.evaluate(
cached_train, return_dict=True)["factorized_top_k/top_100_categorical_accuracy"]
test_accuracy = model.evaluate(
cached_test, return_dict=True)["factorized_top_k/top_100_categorical_accuracy"]
print(f"Top-100 accuracy (train): {train_accuracy:.2f}.")
print(f"Top-100 accuracy (test): {test_accuracy:.2f}.")
Epoch 1/3 WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor. Received: inputs={'user_id': <tf.Tensor 'IteratorGetNext:2' shape=(None,) dtype=string>, 'timestamp': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=int64>}. Consider rewriting this model with the Functional API. WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor. Received: inputs={'user_id': <tf.Tensor 'IteratorGetNext:2' shape=(None,) dtype=string>, 'timestamp': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=int64>}. Consider rewriting this model with the Functional API. WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor. Received: inputs={'user_id': <tf.Tensor 'IteratorGetNext:2' shape=(None,) dtype=string>, 'timestamp': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=int64>}. Consider rewriting this model with the Functional API. WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor. Received: inputs={'user_id': <tf.Tensor 'IteratorGetNext:2' shape=(None,) dtype=string>, 'timestamp': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=int64>}. Consider rewriting this model with the Functional API. 40/40 [==============================] - 10s 175ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0057 - factorized_top_k/top_5_categorical_accuracy: 0.0148 - factorized_top_k/top_10_categorical_accuracy: 0.0238 - factorized_top_k/top_50_categorical_accuracy: 0.0812 - factorized_top_k/top_100_categorical_accuracy: 0.1487 - loss: 14606.0927 - regularization_loss: 0.0000e+00 - total_loss: 14606.0927 Epoch 2/3 40/40 [==============================] - 9s 176ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0026 - factorized_top_k/top_5_categorical_accuracy: 0.0153 - factorized_top_k/top_10_categorical_accuracy: 0.0304 - factorized_top_k/top_50_categorical_accuracy: 0.1375 - factorized_top_k/top_100_categorical_accuracy: 0.2512 - loss: 13958.5635 - regularization_loss: 0.0000e+00 - total_loss: 13958.5635 Epoch 3/3 40/40 [==============================] - 9s 177ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0026 - factorized_top_k/top_5_categorical_accuracy: 0.0189 - factorized_top_k/top_10_categorical_accuracy: 0.0393 - factorized_top_k/top_50_categorical_accuracy: 0.1713 - factorized_top_k/top_100_categorical_accuracy: 0.3015 - loss: 13696.8511 - regularization_loss: 0.0000e+00 - total_loss: 13696.8511 WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor. Received: inputs={'user_id': <tf.Tensor 'IteratorGetNext:2' shape=(None,) dtype=string>, 'timestamp': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=int64>}. Consider rewriting this model with the Functional API. WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor. Received: inputs={'user_id': <tf.Tensor 'IteratorGetNext:2' shape=(None,) dtype=string>, 'timestamp': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=int64>}. Consider rewriting this model with the Functional API. 40/40 [==============================] - 9s 172ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0050 - factorized_top_k/top_5_categorical_accuracy: 0.0323 - factorized_top_k/top_10_categorical_accuracy: 0.0606 - factorized_top_k/top_50_categorical_accuracy: 0.2254 - factorized_top_k/top_100_categorical_accuracy: 0.3637 - loss: 13382.7869 - regularization_loss: 0.0000e+00 - total_loss: 13382.7869 5/5 [==============================] - 1s 237ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0012 - factorized_top_k/top_5_categorical_accuracy: 0.0097 - factorized_top_k/top_10_categorical_accuracy: 0.0214 - factorized_top_k/top_50_categorical_accuracy: 0.1259 - factorized_top_k/top_100_categorical_accuracy: 0.2468 - loss: 30699.8529 - regularization_loss: 0.0000e+00 - total_loss: 30699.8529 Top-100 accuracy (train): 0.36. Top-100 accuracy (test): 0.25.
এটি বেশ কিছুটা ভাল: শুধুমাত্র প্রশিক্ষণের নির্ভুলতাই অনেক বেশি নয়, তবে পরীক্ষার নির্ভুলতাও যথেষ্ট উন্নত হয়েছে।
পরবর্তী পদক্ষেপ
এই টিউটোরিয়ালটি দেখায় যে আরও বৈশিষ্ট্যগুলি অন্তর্ভুক্ত করার সময় এমনকি সাধারণ মডেলগুলি আরও নির্ভুল হতে পারে। যাইহোক, আপনার সর্বাধিক বৈশিষ্ট্যগুলি পেতে প্রায়শই বড়, গভীর মডেলগুলি তৈরি করা প্রয়োজন৷ এটি আরও বিশদে অন্বেষণ করতে গভীর পুনরুদ্ধার টিউটোরিয়ালটি দেখুন।