به نام خدا
همانطور که در پست های قبلی خوندید من برای پروژه پایانی کارشناسیم، تحلیل داده های توییتر رو دنبال کردم و هدفش هم تشخیص اجتماعات بود. اگر پست های قبلی رو نخوندید من لینکشون رو در ادامه میزارم. خوندن پست های قبلی کمک میکنه یه دورنمایی از پروژه داشته باشید و باعث میشه هنگام خوندن این نوشته ابهام کمتری داشته باشید.
جمع آوری داده به مرحله ای رسیده بود که من کاربران فارسی زبان رو اطلاعاتشون رو استخراج کرده بودم. من در پست قبل اطلاعاتی که ذخیره کردم رو نگفتم ولی تو کدهایی که گذاشته بودم معلوم بود. اطلاعاتی که جمع آوری کردم شامل آیدی، یوزرنیم، اسم، لوکیشن، تعداد فالوئرها، تعداد دوستان(منظور همون فالوئینگ ها هست)، تعداد توییت هایی که لایک شده، تعداد توییت های منتشر شده(شامل ریتوییتها) و تاریخ ایجاد اکانت بود. اطلاعات زیاد دیگری نیز وجود داشت ولی من ذخیره نکردم و صرفا به همین اطلاعات بسنده کردم.
در فاز بعدی جمع آوری داده من قصد داشتم اطلاعات بیشتری از کاربران فارسی زبان جمع آوری بکنم. برای این کار از بین یوزر هایی که جمع آوری شده بود افرادی که فالوئر های بیشتری داشتند رو استخراج کردم و فالوئر های این افراد رو دریافت کردم. کد های مربوط به جمع آوری این اطلاعات رو در ادامه خواهید دید.
همانطور که در کد های بالا مشاهده میکنید در ابتدا کتابخانه های مربوط به پایگاه داده ها، Tweepy و ... را ایمپورت میکنیم. توکن ها را از فایل میخوانیم، سپس به پایگاه داده Mysql متصل میشویم و ابجکت های مربوط به API توییتر را میسازیم. من در مرحله قبل اکانت هایی که قصد داشتم فالوئر های آن ها را دریافت بکنم را وارد Mysql کردم. بسیاری از جزئیات و کار هایی که برای این پروژه صورت گرفت است، در پست های تحلیل داده مطرح نکرده ام و مواردی که حس میکردم برای شما مفید هست رو مطرح کردم. به طور مثال کدهای مربوط به انتقال داده ها از Neo4J به SQLSERVER/MySQL مطرح نشده است.
در گام بعدی اطلاعات فالوئر های افرادی که آیدی آن ها را در دیتابیس وارد شده دریافت میکنیم. برای انجام این کار در کتابخانه Tweepy یک تابع وجود دارد، این تابع برای دریافت اطلاعاتی استفاده می شود که نیاز به ارسال بیش از یک درخواست هست. به طور مثال در هر بار ارسال درخواست، آیدی 5 هزار فالوئر دریافت می شود و برای یک فردی که 50 هزار فالوئر دارد این درخواست 10 بار باید ارسال شود و در هر درخواست یک cursor برای ما ارسال می شود تا بتوانیم ادامه داده ها را با فرستادن این آرگومان به سرور دریافت بکنیم. همه ی این موارد در کتابخانه Tweepy با استفاده از تابع Cursor به راحتی صورت می پذیرد و نیاز به پیاده سازی آن ها نیست.
من اطلاعات دریافتی رو در یک جدول جدا ذخیره کردم به این صورت که ستون اول جدول مربوط به آیدی ئی است که فالوئر هایش دریافت شده و ستون دوم نیز آیدی فالوئر ها می باشد.
بعد از این که آیدی فالوئر های این افراد را در پایگاه داده ذخیره شد. از داده های MySQL بکاپ تهیه کردم و آن را به کامپیوتر شخصی انتقال دادم و وارد پایگاه داده MSSQL کردم. حجم داده هایی که در این مرحله به دست آمد به شدت بالا بود و با سختی زیاد و در چندین مرحله توانستم این فایل ها را به کامپیوتر شخصی انتقال بدهم. از بین 1000 نفر فردی که لیست فالوئر های آن ها دریافت شده است حدود 40 میلیون آیدی یوزر به دست آمده است که البته بخش زیادی از آن تکراری می باشد. و حدود 7 میلیون یوزر یونیک به دست آمد. قطعا تمام یوزر ها جزو کاربران فارسی زبان نیستند و ما برای این که احتمال وجود کاربران فارسی زبان رو بیشتر بکنیم باید یک قاعده ای برای جداسازی این افراد انتخاب بکنیم.
تعداد زیادی از این آیدی ها صرفا یکبار در دیتاست تکرار شده اند و چون کاربران فارسی زبان حداقل چندین اکانت فارسی زبان معروف را دنبال می کنند باید تعداد تکرار ها را مبنایی برای جدا سازی قرار دهیم. فرض اولیه این است که اگر آیدی به دست آمده حداقل 40 بار تکرار شده بود جزو کاربران فارسی زبان است. پس از این که این غربال سازی صورت گرفت حدود 400 هزار یوزر به دست آمد و البته برای برخی از این کاربران صرفا آیدی وجود دارد و اطلاعاتی مانند نام و مواردی مانند این در یک مرحله جداگانه دریافت شد.
من این مرحله را چندین بار دیگر نیز تکرار کردم (با توجه به یوزر های جدید اطلاعات بیشتری جمع آوری می شد) ولی به دلیل این که با هر بار انجام دادن این کار درصد خطا برای کاربران فارسی زبان بالا می رود از اضافه کردن بخشی از داده های جمع آوری شده اجتناب کردم. در نهایت از میان 400 میلیون رابطه فالوئر و فالوئینگ که 4000 یوزر اصلی داشت حدود 400 هزار یوزر با اطلاعات کامل وجود داشت.
جمع آوری داده های مربوط به فالوئر و فالوئینگ ها، حدود 45 روز به طول انجامید و فرایند سخت و وقت گیری بود. من سعی کردم به ساده ترین شکل ممکن این موارد رو توضیح بدم و بسیاری از نکات قطعا گفته نشده است.
همانطور که در اولین پست اشاره کردم، در زمان جمع آوری داده من به تئوری گراف آشنا نبودم و همچنین تا به حال با این حجم از داده روبرو نشده بودم بنابر این در فرایند جمع آوری داده سعی کردم خیلی کامل و جامع این کار رو انجام بدم ولی برای پردازش داده ها با محدودیت های سخت افزاری و زمانی روبرو شدم.
برای این تعداد کاربر نه تنها پردازش اطلاعات بسیار زمان بر و وقت گیر است و ممکن است بیشتر از یکسال طول بکشد بلکه شاید نشدنی و غیر ممکن باشد.
من با مشورتی که با استاد راهنمام کردم به این نتیجه رسیدم که میتونم بخش کوچکی از داده ها رو برای تحلیل انتخاب کنم و البته چاره دیگری هم نداشتم و باید برای این که بتونم تو فرصت زمان باقی مانده از پروژه پایانیم دفاع بکنم خیلی سریع پروژه رو به اتمام می رسوندم. در نهایت من دوباره از افرادی که فالوئر های بالایی دارند استفاده کردم و از آن ها برای انجام تحلیل استفاده کردم.
مانند مرحله قبل که من برای جمع آوری داده از اکانت هایی با فالوئر بالا استفاده کردم این بار نیز از افرادی که فالوئر های بالایی داشتند و همچنین یک سری شرایط دیگر مانند تعداد توییت ها یا تعداد فالوئینگ ها و ... استفاده کردم و 1054 گره را فیلتر کردم.
برای انجام تحلیل و پردازش و محاسبات مربوط به گراف، همانطور که اشاره کردم 1054 گره که مربوط به افرادی هستند که فالوئر های بالایی دارند فیلتر شده است. پس از مشخص شدن گره ها من باید روابط این افراد را در قالب یک گراف مدل سازی می کردم.
با توجه به اینکه حجم داده ها به شدت کاهش یافته بود، من دوباره از Neo4j استفاده کردم. روابطی که در این مرحله استخراج خواهیم کرد علاوه بر فالوئر و فالوئینگ ها شامل توییت ها، ریتوییت ها، لایک ها و منشن خواهد بود. در این مرحله بر خلاف مرحله قبل هیچ یوزر جدیدی اضافه نمی شود و روابط صرفا بین نود های موجود ایجاد می شوند.
در ادامه کد های مربوط به جمع آوری داده های ارتباطات بین نود ها را مشاهده می کنید.
در فایل اول ابتدا آیدی هایی که در یک فایل خروجی گرفته شده است را وارد پایگاه داده Neo4j می کنیم و به ازای هر نود یک USER با آیدی مشخص می سازیم. در فایل بعدی اقدام به دریافت اطلاعات تکمیلی هر گره می کنیم. با وجود این که این اطلاعات در گام قبل جمع آوری شده بود ولی به دلیل گذر زمان اطلاعات دچار تغییراتی شده بود و بهتر است که به روزرسانی شود و در همین مدت برخی اکانت ها بسته شده بودند و تغییراتی در آن ها رخ داده بود.
در فایل سوم که اصلی ترین فایل است، اطلاعاتی نظیر توییت و ریتوییت و منشن ها استخراج شده است. در صورتی که در فهم قسمتی از این فایل ها مشکلی بود حتما در کامنت ها بگید تا بیشتر توضیح بدم.
تا اینجا ما یک پایگاه داده با حدود هزار گره و حدود 700 هزار رابطه داریم. که در ادامه تصاویر مربوط به آن در Neo4j را مشاهده می کنید.
در نود ها ما یک نود USER داریم و در روابط هم Follow , Mentions , Qoute , Reply , Retweet را داریم که در ادامه می بینید.
با توجه به این روابط بین هر جفت گره یکتا نیست باید با استفاده از وزن دار کردن گراف، رابطه بین هر جفت گره را یکتا بکنیم. در گام بعد به هر یک از روابط یک نوع وزن می دهیم و این کار را انجام می دهیم. با انجام این کار تعداد روابط کاهش پیدا میکند و همانطور که از تعداد روابط مشخص است انجام تحلیل های گراف در ابعاد بالا به شدت دشوار و نیاز به منابع زیادی دارد.
در پست بعد الگوریتم LPA رو روی داده ها اعمال می کنیم و آخرین پست خواهد بود.
ممنون که تا به اینجا پست ها رو دنبال کردید. اگر نکته ای وجود داره که نیاز به توضیح بیشتر داره و ابهامی وجود داره، خوشحال میشم در کامنت ها برام بنویسید.