تنسورفلو ۶ - رگرسیون خطی ۱

تنسورفلو یک سری api سطح پایین داره که به شما اجازه میده کنترل کامل بر روی محاسبات داشته باشید. یک سری api سطح بالا هم داره که به شما اجازه میده اکثر الگوریتم های هوش مصنوعی رو اجرا کنید مثلا estimators.API سطح پایین: ساخت و بهبود مدل از پایه که برای افراد مبتدی استفاده ازش سختهAPI سطح بالا: الگوریتم تعریف می کنیم و تنسورفلو estimator رو می سازه تعلیم می کنه و ارزیابی میکنه.در این قسمت قراره از estimator استفاده کنیم. ابتدا درباره کاهش گرادیان صحبت می کنیم و سپس با استفاده از دیتاست بوستون به وسیله تنسورفلو قیمت خانه رو تخمین می زنیم.دانلود دیتاست بوستونچگونه یک مدل رگرسیون خطی رو تعلیم دهیمابتدا این که بدونیم رگرسیون خطی چی هست؟فرض کنید که یک نمودار x و y دارید که وقتی به اون دقت می کنید می بینید وقتی که x افزایش پیدا می کنه y هم افزایش پیدا می کنه.مثلا وقتی که x=1 هست y تقریبا 6 هست یا وقتی که x=2 هست y تقریبا برابر 12 هست. همینطور که می بینید شما می تونید یک خط روی این دیتا ها رسم کنید که دقیق شاید نباشه ولی یک روند کلی از دیتا ها رو به شما نشون میده.این خطی که کشیدید یک معادله داره و کار رگرسیون خطی بدست آوردن این معادله هست. به این صورت که متغیر y به وسیله تعدادی متغیر ساخته می شه که در مثال ما فقط به x مربوطه. پس معادله ما به صورت زیر میشه:به این صورت که:متغیر اول b بایاس هست ینی وقتی که x صفر باشه y این مقدار رو داره.متغیر a وزن x هست.متغیر e ارور هست و شامل اطلاعاتی میشه که مدل نمی تونه یاد بگیره.برای مثال اگه متغیر ها به صورت زیر باشهb = 3.8a = 2.78معادله به صورت زیر میشه:y= 3.8 + 2.78xالان شما می تونید هر مقداری رو به جای x قرار بدید و y را پیش بینی کنید.خط قرمز نشان دهنده مقدار نسبت داده شده به y هست به ازای هر x. الان می تونید حتی برای x های بزرگتر از ۲ نیز مقدار y رو تخمین بزنید.برای اینکه مدل دقیق تر باشه میشه بهش متغیر های بیشتری اضافه کرد مثلا می خواییم میزان فروش یک بستنی فروشی رو پیش بینی کنیم. دیتاست ما شامل اطلاعاتی از قبیل آب و هوا، اطلاعات مشتریان مثل حقوق و جنسیت میشهدر تحلیل های سنتی مثلا از متغیر های مختلف میانگین می گرفتیم و سعی می کردیم برای سناریو های مختلف تخمین بزنیم که البته پیش بینی ها دقیق نبوده و به سناریو های موجود محدود می شدیم اما با استفاده از رگرسیون خطی شما می تونید معادله زیر رو داشته باشید:الگوریتم بهترین وزن ها رو برای معادله بالا پیدا میکنه ینی اینکه سعی میکنه هزینه رو کاهش بده (هزینه تفاوت قیمت واقی با قیمت تخمین زده شده هست)الگوریتم چگونه کار میکنه؟الگوریتم ابتدا به صورت تصادفی یک تعدادی وزن اتخاب می کند و برای هر x یک مقدار برای y تخمین می زند. مثلا اگه دیتاست صد عضو دارد صد تا مقدار تخمین زده می شه.با حساب کردن تفاوت بین مقدار واقعی و مقدار تخمین زده شده می توان ارور مدل را به دست آورد. هدف ما اینه که مربع این عدد رو تا حد ممکن کم کنیم که به صفر برسد. این مرحله کاهش میزان ارور هست برای رگسیون خطی این میانگین مربع خطا یا MSE هستبه این صورت که:تتا وزن ها هست که به صورت ضرب ماتریسی در x مقدار تخمینی y بدست می آید.متغیر y هم مقدار واقعی هستمتغیر m هم تعداد مشاهدات در دیتاست هستند.هدف یافتن مناسب ترین تتا برای کاهش MSE هست.اگر میانگین ارور بزرگ باشد ینی اینکه مدل به خوبی کار نمی کنه و وزن ها به درستی انتخاب نشده اند. برای درست کردن وزن ها به یک بهینه ساز نیاز داریم. یک بهینه ساز کاهش گرادیان هست.کاهش گرادیان با گرفتن مشتق وزن ها رو افزایش یا کاهش می ده. اگه مشتق مثبت بشه وزن کاهش پیدا می کنه و اگه منفی بشه وزن افزایش پیدا می کنه. مدل وزن ها رو بروزرسانی میک نه و ارور رو مجددا محاسبه می کنه. این روند تا وقتی که ارور تغییری نکنه ادامه پیدا میکنه. همچنین هر گرادیان ضربدر یک ضریب یادگیری میشه که سرعت یادگیری رو نشان میده.اگ ضریب یادگیری خیلی کوچک باشه زمان زیادی طول میکشه تا مدل یاد بگیره و اگه خیلی بزرگ باشه ممکنه مدل به نتیجه ای نرسهمثلا در عکس بالا مشاهده میشه که حدودا بعد از بیست بار تکرار مدل یک مقدار پایدار برای وزن ها پیدا کرده و به کمترین ارور دست پیدا کرده.یک نکته که باید دقت کنید اینه که ارور صفر نشده برای کمتر کردن ارور باید مثلا متغیر های بیشتر یا اطلاعات بیشتر داشته باشید یا از برآوردگر های مختلفی استفاده کنید.چگونه به وسیله TensorFlow یک مدل رگرسیون خطی بسازیمخب حالا که یه دانشی داریم درباره اینکه قراره چه اتفاقی رخ بده آماده ایم که از estimator های تنسورفلو برای تعلیم اولین مدل استفاده کنیم. می خواییم از دبتاست بوستون استفاده کنیم .دیتاست بوستون متغیر هایی همچون تعداد اتاق ها، میزان مالیات و... دارهقراره دیتاست به چند قسمت تقسیم کنیم به این صورت که: ۴۰۰ سطر برای یادگیری مدل و پیدا کردن وزن ها۱۰۰ سطر برای ارزیابی مدل بر اساس دیتا هایی که در زمان یادگیری مشاهده نکرده۶ سطر برای تخمین عملکرد مدلهدف هم این هست که به وسیله متغیر ها و ویژگی های هر خونه قیمت خونه رو پیش بینی کنیم.اول با پانداس دیتا رو وارد می کنیم و بعد قراره یاد بگیریم چجوری مدل رگرسیون خطی رو با api های سطح بالا بسازیم، یادبدیم، ارزیابی کنیم. اگه می خواستیم از api های سطح پایین استفاده کنیم باید چندتا کار می کردیم:تابع کاهش تعریف می کردیمتابع بهینه سازی تعریف می کردیمماتریس ها رو ضرب می کردیماین مراحل برای شروع یکمی خسته کننده و پیچیده هستمحیط مجازی یادتون نرهوارد سازی دیتااول sklearn نصب کنیدمی تونید با دستور زیر نصب کنید:pip:pip3 install -U scikit-learnconda:conda install scikit-learnسپس باید لایبرری های مورد نظر وارد کنیمimport pandas as pd from sklearn import datasets import tensorflow as tf import itertoolsمرحله ۱) وارد کردن اطلاعات به وسیله pandasابتدا اسم ستون ها رو در متغیر COLUMNS ذخیره می کنیم و بعدش با read_csv دیتا رو وارد می کنیم.COLUMNS = ["crim", "zn", "indus", "nox", "rm", "age","dis", "tax", "ptratio", "medv"]boston_set = pd.read_csv("Boston.csv", skipinitialspace=True,skiprows=1, names=COLUMNS)training_set = boston_set[:400]test_set = boston_set[400:500]prediction_set = boston_set[500:]با خط زیر هم ساختار مجموعه ها رو میبینمprint(training_set.shape, test_set.shape, prediction_set.shape)خب الان می خواییم ویژگی های هر خونه رو از لیبل جدا کنیم لیبل چیزی هست که قراره تخمین بزنیمFEATURES = ["crim", "zn", "indus", "nox", "rm", "age", "dis", "tax", "ptratio"] LABEL = "medv"مرحله ۲ ) تبدیل دیتادر این مرحله باید دیتا های عددی را به فرمت صحیح نشون بدیم برای اینکار تنسورفلو یک متدی داره به اسم tf.feature_column.numeric_columnدر مرحله قبل شما یک لیست تعریف کردید از ویژگی هایی که می خوایید داخل مدل باشه. الان از اون لیست استفاده می کنیم اگه دوست دارید ویژگی خاصی توی مدل نباشه از اون لیست حذفش کنید.feature_cols = [tf.feature_column.numeric_column(k) for k in FEATURES]مرحله ۳) تعریف برآوردگردر این مرحله می خواییم برآوردگر تعریف کنیم. تنسورفلو چند تا برآوردگر پیش ساخته دارهرگرسیونDNNRegressorLinearRegressorDNNLineaCombinedRegressorطبقه بندیDNNClassifierLinearClassifierDNNLineaCombinedClassifierتوی این قسمت از رگرسیون خطی با استفاده از tf.estimator بهره می بریم.این تابع دوتا ورودی داره:feature_columns: متغیر هایی که قراره مدل داشته باشهmodel_dir: مسیر ذخیره سازی مدلاز مسیر ذخیره سازی برای تنسوربرد هم استفاده می کنیم.estimator = tf.estimator.LinearRegressor( feature_columns=feature_cols, model_dir="train")نکته مهم در رابطه با تنسورفلو نحوه ورود دیتا به مدل هست. تنسورفلو به نحوی طراحی شده که با پردازش موزای و پردازش دیتاست های خیلی بزرگ کار کنه و به خاطر محدودیت های منابع ماشین نمیشه همه دیتا رو یک باره وارد مدل کرد. بخاطر همین در هر مرحله یک قسمتی از داده رو وارد می کنیم که بهش میگن Batch.اگه اینکار رو نکنیم مثلا وقتی یه دیتاست یک میلیون سطر داره به مشکل مموری می خوریم..مثلا اگه ۱۰۰ تا سطر داشته باشیم اندازه بچ رو ۱۰ تایی انتخاب می کنیمو یعنی در هر تکرار مدل ۱۰ تا مشاهده رو بررسی می کنه.وقتی مدل یک بار همه دیتا ها رو ببینه یک ایپاک گذرونده. هر epoch به معنی اینه که چند بار همه دیتا ها مشاهده بشه.یک نکته دیگه که باید بگم over fitting هست به این معنی هست که مدل داره اشتباه یاد می گیره یعنی اینکه شما می خوایید ی پترن خاص یاد بگیره ولی مدل بر اساس دیتا هایی که داره مشاهده می کنه فقط داره یاد می گیره و وقتی یه سری دیتا جدید ببینه اشتباه تصمیم می گیره. مثال بخوام بزنم فرض کنید شما تنها چیز قرمزی که توی عمرتون می بینید فقط ماشین باشه و به این نتیجه برسید که هر چیز قرمز ماشینه !! بعد که ی ماشین آبی ببینید بگید که نه این ماشین نیست شما دچار over fitting شدید. برای مقابله با این پدیده یه سری کار ها می کنیم. فعلا در این حد که قبل از هر تکرار دیتا ها رو شافل می کنیم. راستش تنسور فلو این کار ها رو خودش می کنه :-)برای اینکه به تنسورفلو بگیم چجوری به مدل دیتا وارد کن می تونیم از تابع pandas_input_fn استفاده کنیم که ۵ تا پارامتر دارهx: دیتا هاy: لیبل دیتاbatch_size: اندازه بچnum_epoch: تعداد ایپاکshuffle: وضعیت شافل کردنYou need to feed the model many times so you define a function to repeat this process. all this function get_input_fn.def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True): return tf.estimator.inputs.pandas_input_fn( x=pd.DataFrame({k: data_set[k].values for k in FEATURES}), y = pd.Series(data_set[LABEL].values), batch_size=n_batch, num_epochs=num_epochs, shuffle=shuffle)برای ارزیابی مدل اصولا کار های زیر رو انجام می دیمتعلیم مدلارزیابی مدل در یک دیتابیس دیگرتخمین زدنبرآوردگر تنسورفلو سه تابع مختلف برای اعمال فوق ارائه میدهمرحله ۴) تعلیم مدلبا تابع زیر مدل رو تعلیم میدیم به این صورت که هزار مرتبه و هر مرتبه ۱۲۸ سطر و خب از ایپاک هم استفاده نمی کنیم مثلا اگه اینجا ایپاک رو ۱ قرار می دادیم ۴ بار اجرا می شد چونکه: ۱۲۸ ۱۲۸ ۱۲۸ ۱۶ولی ما ایپاک رو none می زاریم و به جاش step رو ۱۰۰۰estimator.train(input_fn=get_input_fn(training_set, num_epochs=None, n_batch = 128, shuffle=False), steps=1000)با تنسوربرد هم می تونیم روند رو بررسی کنیمconda activate hello-tf tensorboard --logdir=./trainمرحله ۵) ارزیابی مدلبرای ارزیابی مدل هم می تونید از تکه کد زیر استفاده کنید.ev = estimator.evaluate( input_fn=get_input_fn(test_set, num_epochs=1, n_batch = 128, shuffle=False)) میزان هزینه مدل رو هم میشه با کد زیر چاپ کردloss_score = ev["loss"] print("Loss: {0:f}".format(loss_score))مرحله ۶) پیش بینی کردنسرانجام مدل آماده میشه برای برآورد و تخمین زدن اگه یادتون باشه ۶ سطر نگه داشتیم برای این مرحلهy = estimator.predict( input_fn=get_input_fn(prediction_set, num_epochs=1, n_batch = 128, shuffle=False))برای چاپش هم:predictions = list(p["predictions"] for p in itertools.islice(y, 6))print("Predictions:{}".format(str(predictions)))خلاصهبرای تعلیم یک مدل باید:تعریف متغیر ها: متغیر های مستقل: Xتعریف برچسب: متغیر های وابسته: yساخت مجموعه تعلیم و تستتعریف وزن های ابتداییتعریف تابع هزینه: MSEبهبود مدل: Gradient descentتعریف:نرخ یادگیریتعداد ایپاکاندازه بچدر این آموزش یادگریفتیم از api های سطح بالای تنسورفلو برای یک رگرسیون خطی استفاده کنیم برای اینکار باید:ستون های ویژگی ها. اگر پیوسته هست tf.feature_column.numeric_column()برآوردگر: tf.estimator.LinearRegressor(feature_columns, model_dir)یک تابع برای ورود دیتا تعداد ایپاک و اندازه بچ: input_fn()بعد مدل برای تعلیم ارزیابی و برآورد آماده هست با توابع: train(), evaluate() , predict()