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

تنسورفلو یک سری 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.8
  • a = 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-learn

conda:

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]

مرحله ۳) تعریف برآوردگر

در این مرحله می خواییم برآوردگر تعریف کنیم. تنسورفلو چند تا برآوردگر پیش ساخته داره

  • رگرسیون
    • DNNRegressor
    • LinearRegressor
    • DNNLineaCombinedRegressor
  • طبقه بندی
    • DNNClassifier
    • LinearClassifier
    • DNNLineaCombinedClassifier

توی این قسمت از رگرسیون خطی با استفاده از 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 های سطح بالای تنسورفلو برای یک رگرسیون خطی استفاده کنیم برای اینکار باید:

  1. ستون های ویژگی ها. اگر پیوسته هست tf.feature_column.numeric_column()
  2. برآوردگر: tf.estimator.LinearRegressor(feature_columns, model_dir)
  3. یک تابع برای ورود دیتا تعداد ایپاک و اندازه بچ: input_fn()

بعد مدل برای تعلیم ارزیابی و برآورد آماده هست با توابع:

train(), evaluate() , predict()