আমরা ভান করতে যাচ্ছি যে আমাদের একটি প্রকৃত পণ্য আছে যা আমাদের উন্নত করতে হবে। আমরা একটি ডেটাসেট অন্বেষণ করব এবং লজিস্টিক রিগ্রেশন, পৌনঃপুনিক নিউরাল নেটওয়ার্ক এবং ট্রান্সফরমারের মতো বিভিন্ন মডেল চেষ্টা করব, সেগুলি কতটা নির্ভুল, তারা কীভাবে পণ্য উন্নত করতে চলেছে, তারা কত দ্রুত কাজ করে এবং সেগুলি ডিবাগ করা সহজ কিনা তা দেখব। এবং স্কেল আপ.
আপনি GitHub- এ সম্পূর্ণ কেস স্টাডি কোড পড়তে পারেন এবং Jupyter Notebook Viewer- এ ইন্টারেক্টিভ চার্ট সহ বিশ্লেষণ নোটবুক দেখতে পারেন।
উত্তেজিত? চলুন এটা পেতে!
কল্পনা করুন আমরা একটি ই-কমার্স ওয়েবসাইটের মালিক। এই ওয়েবসাইটে, বিক্রেতা যে আইটেম বিক্রি করতে চান তার বিবরণ আপলোড করতে পারেন। তাদের ম্যানুয়ালি আইটেমগুলির বিভাগগুলিও চয়ন করতে হবে যা তাদের গতি কমিয়ে দিতে পারে।
আমাদের কাজ হল আইটেম বর্ণনার উপর ভিত্তি করে বিভাগগুলির পছন্দ স্বয়ংক্রিয় করা। যাইহোক, একটি ভুলভাবে স্বয়ংক্রিয় পছন্দ কোন স্বয়ংক্রিয়করণের চেয়ে খারাপ, কারণ একটি ভুল অলক্ষিত হতে পারে, যা বিক্রয়ে ক্ষতির কারণ হতে পারে। তাই আমরা নিশ্চিত না হলে একটি স্বয়ংক্রিয় লেবেল সেট না করা বেছে নিতে পারি।
এই কেস স্টাডির জন্য, আমরা ব্যবহার করব
আমরা নীচে একাধিক মডেল আর্কিটেকচার বিবেচনা করব এবং শুরু করার আগে কীভাবে সর্বোত্তম বিকল্পটি বেছে নেওয়া যায় তা নির্ধারণ করা সর্বদা একটি ভাল অভ্যাস। কিভাবে এই মডেল আমাদের পণ্য প্রভাবিত করতে যাচ্ছে? …আমাদের অবকাঠামো?
স্পষ্টতই, অফলাইনে বিভিন্ন মডেলের তুলনা করার জন্য আমাদের কাছে একটি প্রযুক্তিগত মানের মেট্রিক থাকবে। এই ক্ষেত্রে, আমাদের একটি বহু-শ্রেণীর শ্রেণীবিভাগের কাজ আছে, তাই আসুন একটি সুষম নির্ভুলতা স্কোর ব্যবহার করি, যা ভারসাম্যহীন লেবেলগুলিকে ভালভাবে পরিচালনা করে।
অবশ্যই, একজন প্রার্থীকে পরীক্ষা করার সাধারণ চূড়ান্ত পর্যায় হল AB পরীক্ষা - অনলাইন পর্যায়, যা গ্রাহকরা কীভাবে পরিবর্তন দ্বারা প্রভাবিত হয় তার একটি ভাল চিত্র দেয়। সাধারণত, অফলাইন পরীক্ষার চেয়ে AB পরীক্ষা বেশি সময়সাপেক্ষ, তাই শুধুমাত্র অফলাইন পর্যায়ের সেরা প্রার্থীদের পরীক্ষা করা হয়। এটি একটি কেস স্টাডি, এবং আমাদের প্রকৃত ব্যবহারকারী নেই, তাই আমরা AB পরীক্ষা কভার করতে যাচ্ছি না।
AB-পরীক্ষার জন্য একজন প্রার্থীকে এগিয়ে যাওয়ার আগে আমাদের আর কী বিবেচনা করা উচিত? অফলাইন পর্যায়ে আমরা নিজেদের কিছু অনলাইন পরীক্ষার সময় বাঁচাতে এবং নিশ্চিত করতে পারি যে আমরা সত্যিই সেরা সম্ভাব্য সমাধানটি পরীক্ষা করছি?
ভারসাম্যপূর্ণ নির্ভুলতা দুর্দান্ত, কিন্তু এই স্কোরটি "কীভাবে মডেলটি পণ্যটিকে প্রভাবিত করবে?" প্রশ্নের উত্তর দেয় না। আরও পণ্য-ভিত্তিক স্কোর খুঁজে পেতে আমাদের অবশ্যই বুঝতে হবে যে আমরা কীভাবে মডেলটি ব্যবহার করতে যাচ্ছি।
আমাদের সেটিংয়ে, ভুল করা উত্তর না দেওয়ার চেয়ে খারাপ, কারণ বিক্রেতাকে ভুলটি লক্ষ্য করতে হবে এবং ম্যানুয়ালি বিভাগ পরিবর্তন করতে হবে। একটি অলক্ষিত ভুল বিক্রয় হ্রাস করবে এবং বিক্রেতার ব্যবহারকারীর অভিজ্ঞতাকে আরও খারাপ করবে, আমরা গ্রাহকদের হারানোর ঝুঁকি নিয়ে থাকি।
এটি এড়ানোর জন্য, আমরা মডেলের স্কোরের জন্য থ্রেশহোল্ড বেছে নেব যাতে আমরা শুধুমাত্র 1% ভুল করতে পারি। পণ্য ভিত্তিক মেট্রিক তারপর নিম্নলিখিত হিসাবে সেট করা যেতে পারে:
আমাদের ত্রুটি সহনশীলতা মাত্র 1% হলে আমরা কত শতাংশ আইটেম স্বয়ংক্রিয়ভাবে শ্রেণীবদ্ধ করতে পারি?
সেরা মডেলটি নির্বাচন করার সময় আমরা এটিকে নীচে Automatic categorisation percentage
হিসাবে উল্লেখ করব৷ এখানে সম্পূর্ণ থ্রেশহোল্ড নির্বাচন কোড খুঁজুন।
একটি অনুরোধ প্রক্রিয়া করতে একটি মডেল কতক্ষণ লাগে?
এটি মোটামুটিভাবে আমাদের তুলনা করার অনুমতি দেবে যে যদি একটি মডেল অন্যটির উপর নির্বাচন করা হয় তবে টাস্ক লোড পরিচালনা করার জন্য একটি পরিষেবার জন্য আমাদের কত বেশি সংস্থান বজায় রাখতে হবে।
যখন আমাদের পণ্য বাড়তে চলেছে, প্রদত্ত আর্কিটেকচার ব্যবহার করে বৃদ্ধি পরিচালনা করা কতটা সহজ হবে?
বৃদ্ধি দ্বারা আমরা বলতে পারি:
প্রবৃদ্ধি পরিচালনা করার জন্য আমাদের কি একটি মডেল পছন্দ পুনর্বিবেচনা করতে হবে নাকি একটি সাধারণ পুনরায় প্রশিক্ষণ যথেষ্ট হবে?
প্রশিক্ষণের সময় এবং স্থাপনার পরে মডেলের ত্রুটিগুলি ডিবাগ করা কতটা সহজ হবে?
মডেলের আকার গুরুত্বপূর্ণ যদি:
আমরা পরে দেখব যে উপরের দুটি আইটেম প্রাসঙ্গিক নয়, তবে এটি এখনও সংক্ষেপে বিবেচনা করা মূল্যবান।
আমরা কি নিয়ে কাজ করছি? এর ডেটা দেখুন এবং এটি পরিষ্কার করা প্রয়োজন কিনা তা দেখুন!
ডেটাসেটে 2টি কলাম রয়েছে: আইটেমের বিবরণ এবং বিভাগ, মোট 50.5k সারি।
file_name = "ecommerceDataset.csv" data = pd.read_csv(file_name, header=None) data.columns = ["category", "description"] print("Rows, cols:", data.shape) # >>> Rows, cols: (50425, 2)
প্রতিটি আইটেম 4টি উপলব্ধ বিভাগের মধ্যে 1টি বরাদ্দ করা হয়েছে: Household
, Books
, Electronics
বা Clothing & Accessories
৷ এখানে প্রতি বিভাগে 1টি আইটেমের বর্ণনার উদাহরণ রয়েছে:
গৃহস্থালী SPK বাড়ির সাজসজ্জা ক্লে হস্তনির্মিত ওয়াল হ্যাঙ্গিং ফেস (মাল্টিকলার, H35xW12cm) এই হস্তনির্মিত টেরাকোটা ইন্ডিয়ান ফেস মাস্ক ওয়াল হ্যাঙ্গিং দিয়ে আপনার বাড়িকে আরও সুন্দর করে তুলুন, আগে কখনও আপনি বাজারে এই হস্তনির্মিত জিনিসটি ধরতে পারবেন না। আপনি এটি আপনার বসার ঘর/প্রবেশ লবিতে যোগ করতে পারেন।
বই BEGF101/FEG1-Foundation Course in English-1 (Neeraj Publications 2018 edition) BEGF101/FEG1-Foundation Course in English-1
পোশাক এবং আনুষাঙ্গিক ব্রডস্টার মহিলাদের ডেনিম ডুঙ্গারি ব্রডস্টার দ্বারা ডুঙ্গারি পরা একটি সর্ব-অ্যাক্সেস পাস অর্জন করুন৷ ডেনিমের তৈরি, এই ডুঙ্গারিগুলি আপনাকে আরামদায়ক রাখবে। আপনার নৈমিত্তিক চেহারা সম্পূর্ণ করতে একটি সাদা বা কালো রঙের শীর্ষ সঙ্গে তাদের দল.
ইলেকট্রনিক্স ক্যাপ্রিগো হেভি ডিউটি - 2 ফুট প্রিমিয়াম প্রজেক্টর সিলিং মাউন্ট স্ট্যান্ড ব্র্যাকেট (অ্যাডজাস্টেবল - সাদা - ওজন ক্ষমতা 15 কেজি)
ডেটাসেটে শুধু একটি খালি মান আছে, যা আমরা সরাতে যাচ্ছি।
print(data.info()) # <class 'pandas.core.frame.DataFrame'> # RangeIndex: 50425 entries, 0 to 50424 # Data columns (total 2 columns): # # Column Non-Null Count Dtype # --- ------ -------------- ----- # 0 category 50425 non-null object # 1 description 50424 non-null object # dtypes: object(2) # memory usage: 788.0+ KB data.dropna(inplace=True)
যদিও অনেক নকল বর্ণনা আছে। ভাগ্যক্রমে সমস্ত সদৃশগুলি একটি বিভাগের অন্তর্গত, তাই আমরা নিরাপদে সেগুলি বাদ দিতে পারি৷
repeated_messages = data \ .groupby("description", as_index=False) \ .agg( n_repeats=("category", "count"), n_unique_categories=("category", lambda x: len(np.unique(x))) ) repeated_messages = repeated_messages[repeated_messages["n_repeats"] > 1] print(f"Count of repeated messages (unique): {repeated_messages.shape[0]}") print(f"Total number: {repeated_messages['n_repeats'].sum()} out of {data.shape[0]}") # >>> Count of repeated messages (unique): 13979 # >>> Total number: 36601 out of 50424
সদৃশগুলি সরানোর পরে আমাদের কাছে মূল ডেটাসেটের 55% অবশিষ্ট থাকে৷ ডেটাসেটটি ভালভাবে ভারসাম্যপূর্ণ।
data.drop_duplicates(inplace=True) print(f"New dataset size: {data.shape}") print(data["category"].value_counts()) # New dataset size: (27802, 2) # Household 10564 # Books 6256 # Clothing & Accessories 5674 # Electronics 5308 # Name: category, dtype: int64
উল্লেখ্য, ডেটাসেটের বর্ণনা অনুযায়ী,
ডেটাসেটটি ভারতীয় ই-কমার্স প্ল্যাটফর্ম থেকে স্ক্র্যাপ করা হয়েছে।
বর্ণনা অগত্যা ইংরেজি লেখা হয় না. তাদের মধ্যে কিছু হিন্দি বা অন্যান্য ভাষায় অ-ASCII চিহ্ন ব্যবহার করে লেখা হয় বা ল্যাটিন বর্ণমালায় লিপিবদ্ধ করা হয়, বা ভাষার মিশ্রণ ব্যবহার করে। Books
বিভাগ থেকে উদাহরণ:
यू जी सी – नेट जूनियर रिसर्च फैलोशिप एवं सहायक प्रोफेसर योग्यता …
Prarambhik Bhartiy Itihas
History of NORTH INDIA/வட இந்திய வரலாறு/ …
বর্ণনায় অ-ইংরেজি শব্দের উপস্থিতি মূল্যায়ন করতে, আসুন 2টি স্কোর গণনা করি:
Word2Vec-300
এ উপস্থিত একটি ইংরেজি কর্পাসে প্রশিক্ষণপ্রাপ্ত।
ASCII-স্কোর ব্যবহার করে আমরা শিখি যে শুধুমাত্র 2.3% বিবরণে 1%-এর বেশি নন-ASCII চিহ্ন রয়েছে।
def get_ascii_score(description): total_sym_cnt = 0 ascii_sym_cnt = 0 for sym in description: total_sym_cnt += 1 if sym.isascii(): ascii_sym_cnt += 1 return ascii_sym_cnt / total_sym_cnt data["ascii_score"] = data["description"].apply(get_ascii_score) data[data["ascii_score"] < 0.99].shape[0] / data.shape[0] # >>> 0.023
বৈধ ইংরেজি শব্দের স্কোর দেখায় যে শুধুমাত্র 1.5% বর্ণনায় ASCII শব্দের মধ্যে 70% এর কম বৈধ ইংরেজি শব্দ রয়েছে।
w2v_eng = gensim.models.KeyedVectors.load_word2vec_format(w2v_path, binary=True) def get_valid_eng_score(description): description = re.sub("[^az \t]+", " ", description.lower()) total_word_cnt = 0 eng_word_cnt = 0 for word in description.split(): total_word_cnt += 1 if word.lower() in w2v_eng: eng_word_cnt += 1 return eng_word_cnt / total_word_cnt data["eng_score"] = data["description"].apply(get_valid_eng_score) data[data["eng_score"] < 0.7].shape[0] / data.shape[0] # >>> 0.015
তাই বেশিরভাগ বর্ণনা (প্রায় 96%) ইংরেজিতে বা বেশিরভাগই ইংরেজিতে। আমরা অন্যান্য সমস্ত বিবরণ মুছে ফেলতে পারি, কিন্তু পরিবর্তে, আসুন সেগুলিকে যেমন আছে তেমনই রেখে দেই এবং তারপর দেখুন প্রতিটি মডেল কীভাবে সেগুলি পরিচালনা করে।
আসুন আমাদের ডেটাসেটকে 3টি গ্রুপে বিভক্ত করি:
ট্রেন 70% - মডেল প্রশিক্ষণের জন্য (19k বার্তা)
পরীক্ষা 15% - প্যারামিটার এবং থ্রেশহোল্ড নির্বাচনের জন্য (4.1k বার্তা)
Eval 15% - চূড়ান্ত মডেল নির্বাচন করার জন্য (4.1k বার্তা)
from sklearn.model_selection import train_test_split data_train, data_test = train_test_split(data, test_size=0.3) data_test, data_eval = train_test_split(data_test, test_size=0.5) data_train.shape, data_test.shape, data_eval.shape # >>> ((19461, 3), (4170, 3), (4171, 3))
একটি ভাল বেসলাইন পেতে প্রথমে সহজবোধ্য এবং তুচ্ছ কিছু করা সহায়ক। একটি বেসলাইন হিসাবে আসুন ট্রেন ডেটাসেটের উপর ভিত্তি করে শব্দ কাঠামোর একটি ব্যাগ তৈরি করি।
এর অভিধানের আকার 100 শব্দের মধ্যে সীমাবদ্ধ করা যাক।
count_vectorizer = CountVectorizer(max_features=100, stop_words="english") x_train_baseline = count_vectorizer.fit_transform(data_train["description"]) y_train_baseline = data_train["category"] x_test_baseline = count_vectorizer.transform(data_test["description"]) y_test_baseline = data_test["category"] x_train_baseline = x_train_baseline.toarray() x_test_baseline = x_test_baseline.toarray()
আমি একটি মডেল হিসাবে লজিস্টিক রিগ্রেশন ব্যবহার করার পরিকল্পনা করছি, তাই আমাকে প্রশিক্ষণের আগে কাউন্টার বৈশিষ্ট্যগুলিকে স্বাভাবিক করতে হবে।
ss = StandardScaler() x_train_baseline = ss.fit_transform(x_train_baseline) x_test_baseline = ss.transform(x_test_baseline) lr = LogisticRegression() lr.fit(x_train_baseline, y_train_baseline) balanced_accuracy_score(y_test_baseline, lr.predict(x_test_baseline)) # >>> 0.752
মাল্টি-ক্লাস লজিস্টিক রিগ্রেশন 75.2% সুষম নির্ভুলতা দেখিয়েছে। এটি একটি মহান বেসলাইন!
যদিও সামগ্রিক শ্রেণীবিভাগের গুণমানটি দুর্দান্ত নয়, তবুও মডেলটি আমাদের কিছু অন্তর্দৃষ্টি দিতে পারে। আসুন বিভ্রান্তিকর ম্যাট্রিক্সটি দেখি, পূর্বাভাসিত লেবেলের সংখ্যা দ্বারা স্বাভাবিক করা হয়েছে। X-অক্ষ পূর্বাভাসিত বিভাগ এবং Y-অক্ষ - বাস্তব বিভাগ নির্দেশ করে। প্রতিটি কলামের দিকে তাকিয়ে আমরা বাস্তব বিভাগের বিতরণ দেখতে পারি যখন একটি নির্দিষ্ট বিভাগের পূর্বাভাস দেওয়া হয়েছিল।
উদাহরণস্বরূপ, Electronics
প্রায়শই Household
সাথে বিভ্রান্ত হয়। কিন্তু এমনকি এই সাধারণ মডেল Clothing & Accessories
বেশ সুনির্দিষ্টভাবে ক্যাপচার করতে পারে।
Clothing & Accessories
বিভাগের পূর্বাভাস দেওয়ার সময় এখানে বৈশিষ্ট্যের গুরুত্ব রয়েছে:
Clothing & Accessories
বিভাগের পক্ষে এবং বিপক্ষে শীর্ষ-6 সর্বাধিক অবদানকারী শব্দ:
women 1.49 book -2.03 men 0.93 table -1.47 cotton 0.92 author -1.11 wear 0.69 books -1.10 fit 0.40 led -0.90 stainless 0.36 cable -0.85
এখন আসুন আরও উন্নত মডেলগুলি বিবেচনা করি, বিশেষভাবে সিকোয়েন্সগুলির সাথে কাজ করার জন্য ডিজাইন করা হয়েছে - পুনরাবৃত্ত নিউরাল নেটওয়ার্ক । GRU এবং LSTM হল সাধারণ RNN-এ হওয়া বিস্ফোরিত গ্রেডিয়েন্টের বিরুদ্ধে লড়াই করার জন্য সাধারণ উন্নত স্তর।
আমরা pytorch
লাইব্রেরি ব্যবহার করব বর্ণনাকে টোকেনাইজ করতে, এবং একটি মডেল তৈরি ও প্রশিক্ষণ দেব।
প্রথমত, আমাদের পাঠ্যগুলিকে সংখ্যায় রূপান্তর করতে হবে:
ট্রেন ডেটাসেটকে টোকেনাইজ করার মাধ্যমে আমরা যে শব্দভাণ্ডার পাই তা বড় - প্রায় 90 হাজার শব্দ। আমাদের কাছে যত বেশি শব্দ থাকবে, মডেলটিকে শিখতে হবে এমবেডিং স্পেস তত বেশি। প্রশিক্ষণকে সহজ করার জন্য, আসুন এটি থেকে বিরল শব্দগুলি সরিয়ে ফেলি এবং কেবলমাত্র সেইগুলি ছেড়ে দিই যা কমপক্ষে 3% বিবরণে উপস্থিত হয়। এটি শব্দভান্ডারকে 340 শব্দে কমিয়ে দেবে।
( এখানে সম্পূর্ণ CorpusDictionary
বাস্তবায়ন খুঁজুন)
corpus_dict = util.CorpusDictionary(data_train["description"]) corpus_dict.truncate_dictionary(min_frequency=0.03) data_train["vector"] = corpus_dict.transform(data_train["description"]) data_test["vector"] = corpus_dict.transform(data_test["description"]) print(data_train["vector"].head()) # 28453 [1, 1, 1, 1, 12, 1, 2, 1, 6, 1, 1, 1, 1, 1, 6,... # 48884 [1, 1, 13, 34, 3, 1, 1, 38, 12, 21, 2, 1, 37, ... # 36550 [1, 60, 61, 1, 62, 60, 61, 1, 1, 1, 1, 10, 1, ... # 34999 [1, 34, 1, 1, 75, 60, 61, 1, 1, 72, 1, 1, 67, ... # 19183 [1, 83, 1, 1, 87, 1, 1, 1, 12, 21, 42, 1, 2, 1... # Name: vector, dtype: object
পরবর্তী জিনিস যা আমাদের সিদ্ধান্ত নিতে হবে তা হল ভেক্টরগুলির সাধারণ দৈর্ঘ্য যা আমরা RNN-এ ইনপুট হিসাবে ফিড করতে যাচ্ছি। আমরা সম্পূর্ণ ভেক্টর ব্যবহার করতে চাই না, কারণ দীর্ঘতম বিবরণে 9.4k টোকেন রয়েছে।
যাইহোক, ট্রেন ডেটাসেটের 95% বিবরণ 352 টোকেনের বেশি নয় - এটি ছাঁটাই করার জন্য একটি ভাল দৈর্ঘ্য। সংক্ষিপ্ত বিবরণ দিয়ে কি ঘটতে যাচ্ছে?
তারা সাধারণ দৈর্ঘ্য পর্যন্ত প্যাডিং সূচক সঙ্গে প্যাড করা যাচ্ছে.
print(max(data_train["vector"].apply(len))) # >>> 9388 print(int(np.quantile(data_train["vector"].apply(len), q=0.95))) # >>> 352
পরবর্তী - ক্ষতি গণনা করতে এবং প্রতিটি প্রশিক্ষণের ধাপে ব্যাক-প্রোপাগেশন করতে আমাদের লক্ষ্য শ্রেণীগুলিকে 0-1 ভেক্টরে রূপান্তর করতে হবে।
def get_target(label, total_labels=4): target = [0] * total_labels target[label_2_idx.get(label)] = 1 return target data_train["target"] = data_train["category"].apply(get_target) data_test["target"] = data_test["category"].apply(get_target)
এখন আমরা মডেলে ফিড করার জন্য একটি কাস্টম pytorch
ডেটাসেট এবং ডেটালোডার তৈরি করতে প্রস্তুত। এখানে সম্পূর্ণ PaddedTextVectorDataset
বাস্তবায়ন খুঁজুন।
ds_train = util.PaddedTextVectorDataset( data_train["description"], data_train["target"], corpus_dict, max_vector_len=352, ) ds_test = util.PaddedTextVectorDataset( data_test["description"], data_test["target"], corpus_dict, max_vector_len=352, ) train_dl = DataLoader(ds_train, batch_size=512, shuffle=True) test_dl = DataLoader(ds_test, batch_size=512, shuffle=False)
অবশেষে, আসুন একটি মডেল তৈরি করি।
ন্যূনতম স্থাপত্য হল:
প্যারামিটারের ছোট মান দিয়ে শুরু করে (এম্বেডিং ভেক্টরের আকার, আরএনএন-এ একটি লুকানো স্তরের আকার, আরএনএন স্তরের সংখ্যা) এবং কোনও নিয়মিতকরণ না হওয়া পর্যন্ত, আমরা ধীরে ধীরে মডেলটিকে আরও জটিল করে তুলতে পারি যতক্ষণ না এটি অতিরিক্ত ফিটিং এর শক্তিশালী লক্ষণ দেখায় এবং তারপরে ভারসাম্য বজায় রাখে। নিয়মিতকরণ (RNN স্তরে এবং শেষ রৈখিক স্তরের আগে)।
class GRU(nn.Module): def __init__(self, vocab_size, embedding_dim, n_hidden, n_out): super().__init__() self.vocab_size = vocab_size self.embedding_dim = embedding_dim self.n_hidden = n_hidden self.n_out = n_out self.emb = nn.Embedding(self.vocab_size, self.embedding_dim) self.gru = nn.GRU(self.embedding_dim, self.n_hidden) self.dropout = nn.Dropout(0.3) self.out = nn.Linear(self.n_hidden, self.n_out) def forward(self, sequence, lengths): batch_size = sequence.size(1) self.hidden = self._init_hidden(batch_size) embs = self.emb(sequence) embs = pack_padded_sequence(embs, lengths, enforce_sorted=True) gru_out, self.hidden = self.gru(embs, self.hidden) gru_out, lengths = pad_packed_sequence(gru_out) dropout = self.dropout(self.hidden[-1]) output = self.out(dropout) return F.log_softmax(output, dim=-1) def _init_hidden(self, batch_size): return Variable(torch.zeros((1, batch_size, self.n_hidden)))
আমরা Adam
অপ্টিমাইজার এবং cross_entropy
একটি ক্ষতি ফাংশন হিসাবে ব্যবহার করব।
vocab_size = len(corpus_dict.word_to_idx) emb_dim = 4 n_hidden = 15 n_out = len(label_2_idx) model = GRU(vocab_size, emb_dim, n_hidden, n_out) opt = optim.Adam(model.parameters(), 1e-2) util.fit( model=model, train_dl=train_dl, test_dl=test_dl, loss_fn=F.cross_entropy, opt=opt, epochs=35 ) # >>> Train loss: 0.3783 # >>> Val loss: 0.4730
এই মডেলটি ইভাল ডেটাসেটে 84.3% সুষম নির্ভুলতা দেখিয়েছে। বাহ, কি অগ্রগতি!
RNN মডেলকে স্ক্র্যাচ থেকে প্রশিক্ষণ দেওয়ার প্রধান নেতিবাচক দিক হল এটিকে শব্দের অর্থ নিজেই শিখতে হবে - এটি এমবেডিং স্তরের কাজ। প্রাক-প্রশিক্ষিত word2vec
মডেলগুলি একটি প্রস্তুত-তৈরি এমবেডিং স্তর হিসাবে ব্যবহার করার জন্য উপলব্ধ, যা প্যারামিটারের সংখ্যা হ্রাস করে এবং টোকেনগুলিতে অনেক বেশি অর্থ যোগ করে। pytorch
এ উপলব্ধ word2vec
মডেলগুলির একটি ব্যবহার করা যাক - glove, dim=300
।
আমাদের শুধুমাত্র ডেটাসেট তৈরিতে ছোটখাটো পরিবর্তন করতে হবে - আমরা এখন প্রতিটি বর্ণনা এবং মডেল আর্কিটেকচারের জন্য glove
প্রাক-সংজ্ঞায়িত সূচকগুলির একটি ভেক্টর তৈরি করতে চাই।
ds_emb_train = util.PaddedTextVectorDataset( data_train["description"], data_train["target"], emb=glove, max_vector_len=max_len, ) ds_emb_test = util.PaddedTextVectorDataset( data_test["description"], data_test["target"], emb=glove, max_vector_len=max_len, ) dl_emb_train = DataLoader(ds_emb_train, batch_size=512, shuffle=True) dl_emb_test = DataLoader(ds_emb_test, batch_size=512, shuffle=False)
import torchtext.vocab as vocab glove = vocab.GloVe(name='6B', dim=300) class LSTMPretrained(nn.Module): def __init__(self, n_hidden, n_out): super().__init__() self.emb = nn.Embedding.from_pretrained(glove.vectors) self.emb.requires_grad_ = False self.embedding_dim = 300 self.n_hidden = n_hidden self.n_out = n_out self.lstm = nn.LSTM(self.embedding_dim, self.n_hidden, num_layers=1) self.dropout = nn.Dropout(0.5) self.out = nn.Linear(self.n_hidden, self.n_out) def forward(self, sequence, lengths): batch_size = sequence.size(1) self.hidden = self.init_hidden(batch_size) embs = self.emb(sequence) embs = pack_padded_sequence(embs, lengths, enforce_sorted=True) lstm_out, (self.hidden, _) = self.lstm(embs) lstm_out, lengths = pad_packed_sequence(lstm_out) dropout = self.dropout(self.hidden[-1]) output = self.out(dropout) return F.log_softmax(output, dim=-1) def init_hidden(self, batch_size): return Variable(torch.zeros((1, batch_size, self.n_hidden)))
এবং আমরা প্রশিক্ষণের জন্য প্রস্তুত!
n_hidden = 50 n_out = len(label_2_idx) emb_model = LSTMPretrained(n_hidden, n_out) opt = optim.Adam(emb_model.parameters(), 1e-2) util.fit(model=emb_model, train_dl=dl_emb_train, test_dl=dl_emb_test, loss_fn=F.cross_entropy, opt=opt, epochs=11)
এখন আমরা ইভাল ডেটাসেটে 93.7% সুষম নির্ভুলতা পাচ্ছি। উঃ!
সিকোয়েন্সের সাথে কাজ করার জন্য আধুনিক অত্যাধুনিক মডেল হল ট্রান্সফরমার। যাইহোক, স্ক্র্যাচ থেকে একটি ট্রান্সফরমার প্রশিক্ষণের জন্য, আমাদের প্রচুর পরিমাণে ডেটা এবং গণনামূলক সংস্থানগুলির প্রয়োজন হবে। আমরা এখানে যা চেষ্টা করতে পারি - তা হল আমাদের উদ্দেশ্য পূরণের জন্য প্রাক-প্রশিক্ষিত মডেলগুলির মধ্যে একটিকে সূক্ষ্ম-টিউন করা। এটি করার জন্য আমাদের একটি প্রাক-প্রশিক্ষিত BERT মডেল ডাউনলোড করতে হবে এবং চূড়ান্ত পূর্বাভাস পেতে ড্রপআউট এবং লিনিয়ার লেয়ার যোগ করতে হবে। 4টি যুগের জন্য একটি টিউন করা মডেল প্রশিক্ষণের সুপারিশ করা হয়। আমি সময় বাঁচানোর জন্য শুধুমাত্র 2টি অতিরিক্ত যুগকে প্রশিক্ষিত করেছি - এটি করতে আমার 40 মিনিট সময় লেগেছে।
from transformers import BertModel class BERTModel(nn.Module): def __init__(self, n_out=12): super(BERTModel, self).__init__() self.l1 = BertModel.from_pretrained('bert-base-uncased') self.l2 = nn.Dropout(0.3) self.l3 = nn.Linear(768, n_out) def forward(self, ids, mask, token_type_ids): output_1 = self.l1(ids, attention_mask = mask, token_type_ids = token_type_ids) output_2 = self.l2(output_1.pooler_output) output = self.l3(output_2) return output
ds_train_bert = bert.get_dataset( list(data_train["description"]), list(data_train["target"]), max_vector_len=64 ) ds_test_bert = bert.get_dataset( list(data_test["description"]), list(data_test["target"]), max_vector_len=64 ) dl_train_bert = DataLoader(ds_train_bert, sampler=RandomSampler(ds_train_bert), batch_size=batch_size) dl_test_bert = DataLoader(ds_test_bert, sampler=SequentialSampler(ds_test_bert), batch_size=batch_size)
b_model = bert.BERTModel(n_out=4) b_model.to(torch.device("cpu")) def loss_fn(outputs, targets): return torch.nn.BCEWithLogitsLoss()(outputs, targets) optimizer = optim.AdamW(b_model.parameters(), lr=2e-5, eps=1e-8) epochs = 2 scheduler = get_linear_schedule_with_warmup( optimizer, num_warmup_steps=0, num_training_steps=total_steps ) bert.fit(b_model, dl_train_bert, dl_test_bert, optimizer, scheduler, loss_fn, device, epochs=epochs) torch.save(b_model, "models/bert_fine_tuned")
প্রশিক্ষণ লগ:
2024-02-29 19:38:13.383953 Epoch 1 / 2 Training... 2024-02-29 19:40:39.303002 step 40 / 305 done 2024-02-29 19:43:04.482043 step 80 / 305 done 2024-02-29 19:45:27.767488 step 120 / 305 done 2024-02-29 19:47:53.156420 step 160 / 305 done 2024-02-29 19:50:20.117272 step 200 / 305 done 2024-02-29 19:52:47.988203 step 240 / 305 done 2024-02-29 19:55:16.812437 step 280 / 305 done 2024-02-29 19:56:46.990367 Average training loss: 0.18 2024-02-29 19:56:46.990932 Validating... 2024-02-29 19:57:51.182859 Average validation loss: 0.10 2024-02-29 19:57:51.182948 Epoch 2 / 2 Training... 2024-02-29 20:00:25.110818 step 40 / 305 done 2024-02-29 20:02:56.240693 step 80 / 305 done 2024-02-29 20:05:25.647311 step 120 / 305 done 2024-02-29 20:07:53.668489 step 160 / 305 done 2024-02-29 20:10:33.936778 step 200 / 305 done 2024-02-29 20:13:03.217450 step 240 / 305 done 2024-02-29 20:15:28.384958 step 280 / 305 done 2024-02-29 20:16:57.004078 Average training loss: 0.08 2024-02-29 20:16:57.004657 Validating... 2024-02-29 20:18:01.546235 Average validation loss: 0.09
অবশেষে, সূক্ষ্ম টিউন করা BERT মডেলটি ইভাল ডেটাসেটে 95.1% সুষম নির্ভুলতা দেখায়।
আমরা ইতিমধ্যেই একটি চূড়ান্ত সুপরিচিত পছন্দ করার জন্য বিবেচনা করার জন্য একটি তালিকা স্থাপন করেছি।
এখানে পরিমাপযোগ্য পরামিতি দেখানো চার্ট রয়েছে:
যদিও ফাইন-টিউনড BERT মানের দিক থেকে এগিয়ে আছে, RNN প্রাক-প্রশিক্ষিত এম্বেডিং লেয়ার LSTM+EMB
এর কাছাকাছি দ্বিতীয়, স্বয়ংক্রিয় ক্যাটাগরির অ্যাসাইনমেন্টের মাত্র 3% পিছিয়ে।
অন্যদিকে, ফাইন-টিউনড BERT-এর অনুমান সময় LSTM+EMB
এর চেয়ে 14 গুণ বেশি। এটি ব্যাকএন্ড রক্ষণাবেক্ষণের খরচ যোগ করবে যা সম্ভবত ফাইন-টিউনড BERT
LSTM+EMB
এর উপর নিয়ে আসা সুবিধাগুলিকে ছাড়িয়ে যাবে।
আন্তঃঅপারেবিলিটির জন্য, আমাদের বেসলাইন লজিস্টিক রিগ্রেশন মডেলটি এখন পর্যন্ত সবচেয়ে ব্যাখ্যাযোগ্য এবং যে কোনও নিউরাল নেটওয়ার্ক এই ক্ষেত্রে এটির কাছে হেরে যায়। একই সময়ে, বেসলাইন সম্ভবত সর্বনিম্ন মাপযোগ্য - বিভাগগুলি যোগ করলে বেসলাইনের ইতিমধ্যে নিম্নমানের গুণমান হ্রাস পাবে।
যদিও BERT এর উচ্চ নির্ভুলতার সাথে সুপারস্টারের মতো মনে হচ্ছে, আমরা একটি প্রাক-প্রশিক্ষিত এমবেডিং স্তর সহ RNN-এর সাথে শেষ পর্যন্ত যাচ্ছি। কেন? এটি বেশ নির্ভুল, খুব ধীর নয় এবং জিনিসগুলি বড় হয়ে গেলে পরিচালনা করা খুব জটিল হয় না।
আশা করি আপনি এই কেস স্টাডি উপভোগ করেছেন। আপনি কোন মডেল নির্বাচন করবেন এবং কেন?