تنسورفلو ۸ : دسته بندی خطی

دسته بندی خطی چیست؟در یادگیری تحت نظارت رگرسیون خطی و دسته بندی خطی رایج ترین الگوریتم ها هستند. رگرسیون خطی یک مقدار رو تخمین می زنه و دسته بندی خطی یک دسته رو.دسته بندی میزان احتمال اینکه ورودی متعلق به چه دسته ای هست رو بر میگردونه. و برچسب یک مقدار گسسته هست که نمایانگر یک دسته هست.اگه دو برچسب داشته باشیم دسته بندی دوگانه هست و در غیر این صورت چندگانهمثال دسته بندی دوگانه این هست که آیا یک مشتری برای بار دوم خرید می کند یا نمی کند. و تشخیص نوع حیوان موجود در تصویر چند گانه هست.دسته بندی دوگانه چگونه کار می کند؟همونطور که قبلا یاد گرفتیم یک تابع از دو نوع متغیر ساخته شده متغیر مستقل و متغیر وابسته. در رگرسیون خطی یک متغیر وابسته یک عدد حقیقی بدون مرز هست و هدف اصلی تخمین این عدد با کاهش میانگین مربع خطا هست.در یک دسته بندی دوگانه برچسب دو عدد صحیح مختلف می تونه باشه. مثلا ۰ یا ۱. که مثلا صفر ینی خرید مجدد انجام نمیده و یک ینی خرید مجدد انجام میده.احتمال موفقیت به وسیله <<رگرسیون منطقی>> تشخیص داده میشهتابع به دو قسمت تقسیم میشهمدل خطیتابع منطقیمدل خطیشما از قبل با اینکه چجوری وزن ها محاسبه میشه آشنا هستید وزن ها نمایانگر نحوه ارتباط متغیر های x و y هست. مدل خطی در پایان یک عدد حقیقی بر میگردونه که به وسیله تابع منطقی به صفر یا یک تبدیل میشه.تابع منطقیتابع منطقی یا تابع سیگموئید شکلی شبیه به S داره که خروجی تابع همیشه بین صفر و یک هست و اگه عدد خروجی بین ۰ تا ۰.۴۹ بود مثلا میگیم در دسته ۰ و اگه بین ۰.۵ تا ۱ بود در دسته ۱ قرار می گیره.چگونه کارایی یک مدل دسته بندی خطی را بسنجیم؟دقت مدلکارایی کلی یک دسته بند به وسیله میزان دقت اندازه گرفته می شه. برای محاسبه دقت تعداد پاسخ های درست رو بر تعداد کل مشاهدات تقسیم می کنیم. مثلا دقت ۸۰٪ ینی مدل برای ۸۰ درصد داده ها به درستی تخمین زده.البته یک نکته ای که باید دقت کنیم تعادل داشتن پایگاه دانش هست. مثلا اگه ما یه دیتاستی داشته باشیم درباره تعداد مرگ و میر و ۹۵ ٪ داده ها عضو دسته مرگ باشند و بقیه عضو دسته کسایی که فوت نکردن. اگه مدل ما همیشه فوت کردن رو پیش بینی کنه می تونه دقت ۹۵ ٪ داشته باشه!!!!ماتریس درهم‌ریختگیماتریس درهم‌ریختگی دقت یک دسته بند رو بر اساس مقایسه مقدار واقعی و مقدار تخمین زده شده محاسبه می کنه و دارای اجزا زیر هست:مثبت درست: TP : مقدار تخمین زده شده به درستی به عنوان درست تخمین زده شده استمثبت نادرست: FP : مقدار تخمین زده شده به اشتباه به عنوان درست تخمین زده شده استمنفی نادرست : FN: مقدار تخمین زده شده به اشتباه به عنوان نادرست تخمین زده شده استمنفی درست: TN : مقدار تخمین زده شده به درستی به عنوان نادرست تخمین زده شده استدقت و حساسیتبه وسیله ماتریس درهم‌ریختگی میشه به طور دقیق تر کارایی رو محاسبه کرد.صحت (Precision)معیار صحت نشان می دهد پیش بینی کلاس های مثبت چه تعداد درست است.وقتی که مدل به درستی تمام مقادیر مثبت را پیش بینی کرده مقدار یک هست.این معیار به تنهایی کافی نیست زیرا مقادیر منفی را در نظر نمی گیرد عموما با معیار حساسیت باهم بررسی می شود.حساسیت(Recall)حساسیت نسبت مقادیر مثبت درست تخمین شده رو نشون میده. این معیار نشان می دهد که چه مقدار یک مدل در تشخیص اعضا کلاس مثبت خوب عمل می کند.دسته بندی خطی با TensorFlowبرای این آموزش از داده های سرشماری استفاده می کنیم. هدف این است که با استفاده از مقادیر دیتاست سرشماری سطح درآمد فرد رو تخمین بزنیم که خروجی دوگانه هست. برای مقادیر بیشتر از 50k یک و در غیر این صورت صفر بر می گرداند.دیتاست شامل مقادیر زیر می شود:محل کارتحصیلاتوضعیت ازدواجاشتغالرابطهنژادجنسیتکشور اصلیو مقادیر پیوسته:agefnlwgteducation_numcapital_gaincapital_losshours_weekبا این آموزش قراره با دسته بندی توسط تنسورفلو آشنا بشیم و اینکه چجوری دقت مدل رو افزایش بدیم.مرحله ۱) ورود داده هاابتدا لایبرری ها رو وارد می کنیمimport tensorflow as tf import pandas as pdسپس دیتا ها رو وارد می کنیم.## Define path data COLUMNS = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital', 'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss', 'hours_week', 'native_country', 'label'] PATH = "https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data" PATH_test = "https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.test"df_train = pd.read_csv(PATH, skipinitialspace=True, names = COLUMNS, index_col=False) df_test = pd.read_csv(PATH_test,skiprows = 1, skipinitialspace=True, names = COLUMNS, index_col=False)print(df_train.shape, df_test.shape) print(df_train.dtypes)تنسورفلو برای تعلیم مدل نیاز به یک مقدار Boolean داره برای کلاس بندی داده ها. و باید string ها رو به int تبدیل کنیمlabel = {'<=50K': 0,'>50K': 1} df_train.label = [label[item] for item in df_train.label] label_t = {'<=50K.': 0,'>50K.': 1} df_test.label = [label_t[item] for item in df_test.label]print(df_train["label"].value_counts()) ### The model will be correct in atleast 70% of the case print(df_test["label"].value_counts()) ## Unbalanced label print(df_train.dtypes)مرحله ۲) تبدیل داده هاباید داده ها رو برای ورود به مدل آماده کنیم. تخمین گر نیاز به لیست ویژگی ها برای تعلیم مدل داره و از این رو باید داده ستون ها به tensor تبدیل شود.یک کار خوب تعریف دو لیست از مقادیر بر حسب نوع آن هاست (پیوسته و گسسته)و سویژگی های این دیتاست از دو نوع هستند.IntegerObjectویژگی های مختلف بر حسب گروه آن ها در زیر می بینید:## Add features to the bucket: ### Define continuous list CONTI_FEATURES = ['age', 'fnlwgt','capital_gain', 'education_num', 'capital_loss', 'hours_week'] ### Define the categorical list CATE_FEATURES = ['workclass', 'education', 'marital', 'occupation', 'relationship', 'race', 'sex', 'native_country']در کد زیر مقادیر پیوسته رو به تنسور های با مقادیر عددی تبدیل می کنیم.این کار برای ساخت مدل اجباریه. همه مقادیر مستقل باید به نوع تنسور صحیح خود تبدیل شود.def print_transformation(feature = "age", continuous = True, size = 2): #X = fc.numeric_column(feature) ## Create feature name feature_names = [ feature] ## Create dict with the data d = dict(zip(feature_names, [df_train[feature]])) ## Convert age if continuous == True: c = tf.feature_column.numeric_column(feature) feature_columns = [c] else: c = tf.feature_column.categorical_column_with_hash_bucket(feature, hash_bucket_size=size) c_indicator = tf.feature_column.indicator_column(c) feature_columns = [c_indicator] ## Use input_layer to print the value input_layer = tf.feature_column.input_layer( features=d, feature_columns=feature_columns ) ## Create lookup table zero = tf.constant(0, dtype=tf.float32) where = tf.not_equal(input_layer, zero) ## Return lookup tble indices = tf.where(where) values = tf.gather_nd(input_layer, indices) ## Initiate graph sess = tf.Session() ## Print value print(sess.run(input_layer)) print_transformation(feature = "age", continuous = True) continuous_features = [tf.feature_column.numeric_column(k) for k in CONTI_FEATURES]برای تبدیل داده های گسسته راه های مختلفی وجود داره یکی اینکه مثلا اگه داده ها محدود هستن تبدیل به id شود مثلا همسر، شوهر،مجرد بشه ۱ ۲ ۳یک راه دیگه اینه که هر متغییری یک ستون جدا بشه و مقدار صفر یا یک داشته باشه مثلا ستون مرد و ستون زن بجای تک ستون جنسیتprint_transformation(feature = "sex", continuous = False, size = 2)relationship = tf.feature_column.categorical_column_with_vocabulary_list( 'relationship', [ 'Husband', 'Not-in-family', 'Wife', 'Own-child', 'Unmarried', 'Other-relative'])خود تنسورفلو یک متد خوب برای تبدیل متغیر های گسته داره که در زیر می بینید. تعداد باکت هم ینی این که تنسورفلو در کل چه تعداد گروه می تونه بسازه:categorical_features = [tf.feature_column.categorical_column_with_hash_bucket(k, hash_bucket_size=1000) for k in CATE_FEATURES]مرحله ۳) یادگیری مدلبرای تعریف مدل از کد زیر استفاده می کنیم که ورودی ها به ترتیب تعداد کلاس های طبقه بندی، دایرکتوری مدل و ستون های مدل هستmodel = tf.estimator.LinearClassifier( n_classes = 2, model_dir="ongoing/train", feature_columns=categorical_features+ continuous_features)و در کد های زیر تابع ورودی داده ها رو می سازیمFEATURES = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital', 'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss', 'hours_week', 'native_country'] LABEL= 'label' 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)و با کد های زیر شروع می کنیم مدل رو تعلیم بدیمmodel.train(input_fn=get_input_fn(df_train, num_epochs=None, n_batch = 128, shuffle=False), steps=1000)برای تخمین میزان کارایی مدل از کد زیر استفاده می کنیمmodel.evaluate(input_fn=get_input_fn(df_test, num_epochs=1, n_batch = 128, shuffle=False), steps=1000)اگه دقت کنید دقت مدل زیاده این هم بخاطر اینه که مدل حتی اگه شانسی هم تخمین بزنه چون دیتا ها متعادل نیستن می تونه تخمین خوبی داشته باشه ولی اگه دقت کنید مقادیر صحت و حساسیت پایینه که یعنی مدل مشکل داره و باید بهبودش داد.مرحله ۴) بهبود مدلخب توی آموزش قبل یاد گرفتید چگونه با استفاده از اثر تعاملی دقت رو بهبود ببخشیم توی این قسمت قراره متغیر های چند جمله ای رو امتحان کنیم و به این دلیل هست که شاید بین متغیر ها و خروجی شاید ارتباط خطی نباشه. دو راه برای بدست آوردن غیری خطی بودن در مدل هستافزودن متغیر چند جمله ایدسته بندی مقادیر پیوسته در بسته های گسستهمتغیر چند جمله ایگاهی برای مدل کردن و تخمین برخی از داده ها مدل به صورت خطی با نتیجه مرتبط نیست مثلا در تصویر زیر بجای یک خط صاف یک خط خمیده بهتر بر روی داده ها قرار می گیره برای همین نیاز هست از متغیر های چند جمله ای مثل X^3 و.... استفاده کنیمدر مثال ما سن با میزان درآمد رابطه خطی نداره. مثلا در بچگی میزان درآمد صفر هست و کم کم بیشتر میشه و در سنین پیری و بازنشستگی کمتر میشه. حدودا مثل یک U برعکس هست.مثلا میشه یک توان دو به مدل اضافه کرد و ببینیم دقت چه تغییری می کنه.یک تابع می سازیم که دیتاست آموزش و آزمون و نام متغیر رو بگیره و توان دو رو به دیتاست ها اضافه کنه:def square_var(df_t, df_te, var_name = 'age'): df_t['new'] = df_t[var_name].pow(2) df_te['new'] = df_te[var_name].pow(2) return df_t, df_te سپس تابع رو صدا می زنیم.df_train_new, df_test_new = square_var(df_train, df_test, var_name = 'age') print(df_train_new.shape, df_test_new.shape) و به لیست متغیر های پیوسته اضافه می کنیمCONTI_FEATURES_NEW = ['age', 'fnlwgt','capital_gain', 'education_num', 'capital_loss', 'hours_week', 'new'] continuous_features_new = [tf.feature_column.numeric_column(k) for k in CONTI_FEATURES_NEW] و بعد مدل جدید رو می سازیم البته model_dir رو عوض باید کنیم model_1 = tf.estimator.LinearClassifier( model_dir="ongoing/train1", feature_columns=categorical_features+ continuous_features_new)سپس آموزش میدیمmodel_1.train(input_fn=get_input_fn(df_train, num_epochs=None, n_batch = 128, shuffle=False), steps=1000)و سپس ارزیابیmodel_1.evaluate(input_fn=get_input_fn(df_test_new, num_epochs=1, n_batch = 128, shuffle=False), steps=1000)دقت از ۷۶ شد ۷۹ :دی با دسته بندی مقادیر پیوسته و استفاده از اثر متقابل میشه بهترش کردفشرده سازی و اثر متقابلخب تا اینجا مدل نتونست بازم رابطه سن و درآمد رو درست تشخیص بده یک قدم دیگه اینه که سن ها رو به یک سری مرز سنی تبدیل کنیم برای این کار از کد زیر استفاده می کنیمage = tf.feature_column.numeric_column('age') age_buckets = tf.feature_column.bucketized_column( age, boundaries=[18, 25, 30, 35, 40, 45, 50, 55, 60, 65])یک راه دیگه برتی بهبود مدل استفاده از اثر متقابل متغیر هاست که تنسورفلو یک راهکاری در اختیار ما قرار میده تحت عنوان feature crossing که راهی هست برای ساخت متغیر های جدید از متغیر های موجود که برای مدل دسته بندی خطی که نمی تونه اثر متقابل رو تشخیص بده مفید هست.education_x_occupation = [tf.feature_column.crossed_column( ['education', 'occupation'], hash_bucket_size=1000)] age_buckets_x_education_x_occupation = [tf.feature_column.crossed_column( [age_buckets, 'education', 'occupation'], hash_bucket_size=1000)]ورودی hash_bucket_size تعداد کلاس های مختلف ایجاد شده هستbase_columns = [ age_buckets, ] model_imp = tf.estimator.LinearClassifier( model_dir="ongoing/train3", feature_columns=categorical_features+base_columns+education_x_occupation+age_buckets_x_education_x_occupation)FEATURES_imp = ['age','workclass', 'education', 'education_num', 'marital', 'occupation', 'relationship', 'race', 'sex', 'native_country', 'new'] 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_imp}), y = pd.Series(data_set[LABEL].values), batch_size=n_batch, num_epochs=num_epochs, shuffle=shuffle) آموزش و ارزیابی مدل جدیدmodel_imp.train(input_fn=get_input_fn(df_train_new, num_epochs=None, n_batch = 128, shuffle=False), steps=1000)model_imp.evaluate(input_fn=get_input_fn(df_test_new, num_epochs=1, n_batch = 128, shuffle=False), steps=1000)خب الان دقت شد ۸۳.۵۸در پایان با جلو گیری از over fit شدن مدل رو بهبود میدیم.مرحله ۵) بهبود پارامتر ها: Lasso & Ridgeیک مدل با دو مشکل می تونه روبرو بشه overfitting یا underfitting.اولی Overfitting: مدل قابلیت تعمیم به داده های جدید برای تخمین زدن رو ندارهدومی Underfitting: وقتی که مدل قابلیت پیدا کردن الگو داده ها رو نداره مثلا استفاده از رگرسیون خطی برای داده های غیر خطیبرای جلوگیری از overfitting و عمومی تر کردن مدل تکنیک هایی وجود داره مثل:L1: LassoL2: Ridgeداخل تنسورفلو شما می تونید این دو بهبود دهنده رو به مدل اضافه کنید.البته خودتون با تغییر این دو پارامتر سعی کنید مدل رو بهبود بدید ببینید چقدر میشه بهتر کردmodel_regu = tf.estimator.LinearClassifier( model_dir="ongoing/train4", feature_columns=categorical_features+base_columns+education_x_occupation+age_buckets_x_education_x_occupation, optimizer=tf.train.FtrlOptimizer( learning_rate=0.1, l1_regularization_strength=0.9, l2_regularization_strength=5)) model_regu.train(input_fn=get_input_fn(df_train_new, num_epochs=None, n_batch = 128, shuffle=False), steps=1000)model_regu.evaluate(input_fn=get_input_fn(df_test_new, num_epochs=1, n_batch = 128, shuffle=False), steps=1000) در آموزش بعدی با متد های کرنل سعی می کنیم دقت رو افزایش بدیمخلاصهبرای آموزش یک مدل باید:تعریف ویژگی ها: متغیر های مستقل : Xتعریف برچسب: Dependent variable: yساخت مجموعه های آموزش و آزمونتعریف وزن های ابتداییتعریف تابع کاهش: MSEبهبود مدل: Gradient descentتعریف:نرخ یادگیریتعداد ایپاکاندازه دسته هاتعداد کلاس هابرا استفاده از تنسورفلو باید مقادیر زیر رو تعریف کنید:ستون های ویژگی ها. tf.feature_column.numeric_column برآوردگر tf.estimator.LinearClassifier(feature_columns, model_dir, n_classes = 2)یک تابع برای ورود داده ها اندازه دسته ها و ایپاک ها: input_fn()سپس آموزش و ارزیابی مدلبرای بهبود مدل:استفاده از متغیر های چند جمله ایاثر متقابل: tf.feature_column.crossed_columnاضافه کردن پارامتر تنظیم