{"nbformat":4,"nbformat_minor":0,"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.8.3"},"colab":{"name":"2022-01-26-social.ipynb","provenance":[{"file_id":"https://github.com/recohut/nbs/blob/main/raw/T354054%20%7C%20Predicting%20Future%20Friendships%20from%20Social%20Network%20data.ipynb","timestamp":1644673008974},{"file_id":"https://github.com/sparsh-ai/general-recsys/blob/T426474/Case_Study5/Section23.ipynb","timestamp":1637511334076}],"collapsed_sections":[]}},"cells":[{"cell_type":"markdown","metadata":{"id":"UR8sEDb_SEVh"},"source":["# Predicting Future Friendships from Social Network data\n","\n","## Predicting future friendships from social network data\n","\n","Welcome to FriendHook, Silicon Valley’s hottest new startup. FriendHook is a social networking app for college undergrads. To join, an undergrad must scan their college ID to prove their affiliation. After approval, undergrads can create a FriendHook profile, which lists their dorm name and scholastic interests. Once a profile is created, an undergrad can send *friend requests* to other students at their college. A student who receives a friend request can either approve or reject it. When a friend request is approved, the pair of students are officially *FriendHook friends*. Using their new digital connection, FriendHook friends can share photographs, collaborate on coursework, and keep each other up to date on the latest campus gossip.\n","\n","The FriendHook app is a hit. It’s utilized on hundreds of college campuses worldwide. The user base is growing, and so is the company. You are FriendHook’s first data science hire! Your first challenging task will be to work on FriendHook’s friend recommendation algorithm.\n","\n","Sometimes FriendHook users have trouble finding their real-life friends on the digital app. To facilitate more connections, the engineering team has implemented a simple friend-recommendation engine. Once a week, all users receive an email recommending a new friend who is not yet in their network. The users can ignore the email, or they can send a friend request. That request is then either accepted or rejected/ignored.\n","\n","Currently, the recommendation engine follows a simple algorithm called the *friend-of-a-friend recommendation algorithm*. The algorithm works like this. Suppose we want to recommend a new friend for student A. We pick a random student B who is already friends with student A. We then pick a random student C who is friends with student B but not student A. Student C is then selected as the recommended friend for student A."]},{"cell_type":"markdown","metadata":{"id":"rzhafgGjFh_8"},"source":["![image.png](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUwAAAEyCAIAAAAeJH65AAAgAElEQVR4nOydd5xV1dX319r7nNumV/ow9D7UKQxDszcUUEHFLoItiSYxefKmmGaKic+jsaCigmCvoLGgUdrADL33AYYO02duv/ecvd4/NuDEaECY2/f3c/+YmQ/cu+85+3dW2WvvhaZpgiLsEBFjrLm58cknnvti0cLk5KMOBxIBEEV6aCGHADjH5iZyudtdetnEn/7sh8nJKUIIRIz00OITVCIPP0QEgD6f+4Ypt3vdnz7ym9Q+vTgyKe8EmehkGFh9QPzyV4057a9/Zd7zum6VD75IDywOUSIPN0RERJqm/fL//aF86d8Wvp+ZnBL0eAghYQQOQASIYLMxf0C/+praktKH//SXRwzDQERlz9scJfJwY5om53zH9p033jBp1lPOoiLe0mJyHulhRQLDgLQ0XLUK7n3A8eHH/8rPz1NOeyhQ3lG4ISJE/PzzJXmdjpeU6C6X0DRATMSXpoHLBcMKsV+/lg8XfgEAQiiT0/YokYcVIuKcA8D27bvGj0chCCD+M23fBSIIAQ4769/Pu37d6kgPJ25RIg83DDEY9B3Yf6BvH50xSoBs+n+DMTID1DWPO531pmlqmpboVyQEKJGHHcRAIFBf32CzMwAR6dFEGgRTQMeOwLkwDTOBco9hRIk8AiAiMlQm6zS6TowBqJRbaFAijwxK4a0hSoQioIihRK5QxDlK5ApFnKNErlDEOUrkCkWco0Qet3xrKkvltxIQJfK4BfGbkpbbQhSJhhJ5fCKX4nUdT+ucCDRN7fJKRJTI4w0hwGrFL5cEpt3e8vgTXouFCQLThKRktnhp8IZbmj78OJCcwgwDTAGGAUEDTm9ENM2TfzQMMEwQrR4Qpqlc/VhFi/QAFG0MAWga7Kky//lPb8Wq4G23WDPTmUEUDMKrb/o+/cw3eLCF2dA0IT0ZLQ4EhKCXXG5ChJQUlM8IACACj4eCQQIAzjElBbxeMAxSjkDMoUQelyAAZOVoXj98/Gngnhl2twsOHjIr1wQBGGcARA4Hrt9krFtvBA0YPIiXFOqGAeUrjKQk2LXHZAxsViwYpHVoz4SA5hZaVm4MGsgz0plpKp3HGErkcQhj6PVRj+48aMDipcE7b7db7fjpokDXLtztJJebiPAvf3c/+5y3Q0fe2Ciam8Xf/pxyz922R/7o3rTZ8PiofTtmGDDpGuvjf0qy2/H9hf57fujcvj6TMVCHjMQcKiaPSwgRAkG6fZptaXlg717TYoXX3vRddomlfQdOBKaXPv088NCPHNu2Zh49kj2mzPL0cx60omEC16BicfqqZRl332mbN9/X2ETChFff8F9+iaVzRx4MKjMeeyiRxyeIEAjA6DLd64Vt240dW83DR8QVl1g8HiIC3YGvvpw6Yij/za+MaTf71m8KJiUhAHh9dPGFlkED9fbt2NVXWBmH5SuCtXXiqyWBG6bYdB1Ewm+NjUWUux6fIILfT507sSsvt7z5rv/ocZGehkOG626PYAwCPnjkj+5PPvUPGqQPG6a1y2XBIBCBaVBGOkOk+noaNJgPLtDeXeA/fFTkdWGjinW3R5nxmERZ8vgEEQHRouPECdZVa4LzX/fdcqNNABJhcjIeOWi8845n7uzUipUZzzyd2rkTN01iDBlDAGAMEEFjeNs0W+Wa4N+f8FxysaVzHvP7SZ2YHIuomxaXYCBAPi81N9OF4yxCwPp1wQlXWpGRx01uDyUno93B5szzzZnjnXZT06ef+gHB7xE+H/n8BACMgdtJl19qYQyOHzXvuNnmdSuFxyrKXY83GELAL0oKdYuOug4ZGfir/3F4PNCxAwZc4qEf2gcN0LLasZdfSHtutvfll31Fhdpbr6Vt22HUHhcz7rK3b8cCAWAMAKlTB1Y2Ut+ewQYO1AIBVRIbqyiRxxuI4PPTmDL9grG6P0Aul5h+mw0QfD7yeuhXP3eYBrQ0iEkTLNdOtBAB5yBMuPoqi99P982wCQGBAAGAywV79xmffRH4+U8cSQ5sbBJaQh4OHwcoDywOQYRgkDxekjtSPF7yeEj+3eOhQJDkH10u8niopYVcbvJ6CQC8XgoEiAjsdnzjHf+Yixp6dNNuvN7m8YDy1WMXZcnjE9m9QNJan6d/Pv1Dayf89B8NA8aN0f/yx5TLL7FkZaLfL5TIYxclcsU3kY5A/758+DDN5aRAQKXcYhslcsW3gAg+H3k8xLnKt8U8SuSKb4cxFYfHCeo2KhRxjhJ5ZFDnsyjChhJ5BCAi1Yj7G6irETqUyCOApmlpqWnBgFDXHwgQobaWBfwCE7iLc0hJ+EkWdojIarV37NR+/wFTiETPXRMB1/HwYcPuSOWaZqojKUKAEnlYQUTTNAGwb78+lZVBzliCN+slQkG0bZveNb8PY8w0TeW3tzlK5JHhwovG7tiZs6/asFhQiASd1qYJDgfs2Sk2bnJMmnwZAHCu6uPbHlQOUpiRTYsR4YYpt6enfPTCS2ktDUZino7IGKak6Pfe39zUMvHNt18WgohIWfI2R4k8AgghOOd7du+5ZdrNpSW7HvlNmt2BFMp8u0zmn8P7k2miPESiTSEiROb1waOPNn+yqOvCj97t3r2HaZrKkocCJfLIIITQNG3Lls0/+fGvG+tW9O/v1XWNQta+wGazBYOGYRjfV608NVV4PBQMtq3OEdHnM/bssadllPz5r78bPny4YRhMVdiFBiXyiGGapq7rAb/3y6/K9+091NTYGIpUOwKYQqxatapLly5d8/JM0/wen0JU9+wLqVdeZu3di3y+tipzRQDTNNu1b9elS4ex40Y6HMlK4SFF1a5HDM65YRi6xXb55ReH9IOOHTtiS6IH7rvPbk/6vv+3wdMgWpzZP3sgFAMDAABSCg81SuSRhDEmhJDrRqEIyImIMfbJp4v69OlntTkCgcDZfxCZJtM062237p801bJ2XdLQIULG5203NiLinCuFhxol8giDiJoWkrsg03v79++vraubeM01QMQ5/x6PEkQSwtGnd/LI4vqnnk1+6XkmHxAq+x1rqIdofCLXohCxfOXK/v37Z2Vlfe/VqVN6zn3wAe+6Df6qvcg5qe4KMYgSeXxCAIyxAwcOHDp0qKy0VJyTOBFRCGEvGJQ0srju+RdDsZamCANK5HEKEQAsXbasV69e6enp5yZyQAQhQIjs+2a6vlziq9rLGFPGPOZQIo9DhBCMsaPHjh07fnx0WZn00s8tsYeMCdN0DB3iKBxe9/RzwJjaKhZzKJHHIYjIGFuxYkV+164dO3SQmj/n9wIAECLzrtudn//Lt6cKOSNVWxFTKJHHG3LZ7PiJE3uqqsaNHSuEOM9COmRMACSPLLb27VM/Z56KzGMOJfJ4Q0p68ZIlPXr0yM3NPS8zLkEE0wSAnB/d7/r082BNLTIGIavAVbQ5SuRxhZT0sWPHqqqqigsL26rABhkTQiSXlerdu9XNegFl+k3pPEZQIo8rZDS+dt26jh07duvWrQ3M+Kn3BSGQsewH7m355yeBI0eR89Btp1G0LUrk8YMsd2lsbNy2ffsF48effzTeGmSMiFLGj9FycxpeeVV57DGEEnn8IFNuy5cv79ChQ9cuXdrMjEsQyTCQKGvG9MZXXzfq6pFzpfOYQIk8ThBCcMbqGxp27Nw5pqysDXeSfA3nZIrUSy7Uu3Spn/8aMrWWFhsokccJcutIRWVlSmpq9+7dpVVv848gEsxuz55xV/M77xsNjaqaPSZQIo8HZDTu8Xo3btwo18bPsY71TEjrnTbxauZwNL71rvLYYwIl8nhA2u3Kioqc7Ow+vXuH8DhERDJNZJh9/8yGOa+YLpfSefSjRB7zyEManU7n+o0bS0tLGWOhPfOUMRIi5aILmNVaP3c+IqrIPMpRIo8HOOdr161LSkoaOGBAKKLx1iBjJIinpGTcclPzewuEz4eaBioyj2KUyGMbKWmf17uyoqJs1CgACFE03hpkSEJk3DqN/P7mjz6RS+ih/lDFOaNEHttIka+oqEhKSurVq1eYmhMgkmlymy1r+h21zzwn/IGQrNgp2gh1b2IYKWmv17tpy5aS4mKb1Rq+jsiIZBjp104CIZrefR85J8MIx+cqvj9K5DGMNONbtmxBohEjRoQ6Gm8NMiaIeFpq2sQJ9S/OMb1e1DSVZo9OlMhjFSlpwzDKV64cPXo0ZywM0XhrEJGEyLrzdqOuzvnFl4ioIvPoRIk8VpEiX7N2Led84IABIuytAmVhjJaRnnn7LfXPvxjSXm6K80GJPCY5XeK2evXqwQUFVqtVRKSztzTmt91i1NS2fP6lqmaPTpTIYxJpxvfu3esPBIqLisIZjbcGGSNTaNlZ6ddPrn9utmyBqpz2aEOJPCaRkl66bFlJSYndbg9fUv0/QZCRuX/ffueSZciYKoyJNpTIYw8p6c1btvh8vmFDh0ZS4TL9ZppaVmbaNVfVPvEUAKljHqMNJfIY43RSfWVFxbChQ1OSk82IROOnQQREIsq887bgkWOuilWMcxWZRxVK5DGGTLnt2r27rq5uZElJGx//ck7IyNzWvVvKRRfUP/8SCQGIqgdD9KBEHmPINoZLly0bMXx4hKPxfxsWgBDZP7jPu36jZ+Mm1U0pqlAijyWk3d6zZ4/L5SouLg5z9ct/ARGFaVrzOqdccVnt408CY8Ci4NGjAAAl8hhCOuoEsLy8fED//pkZGdHgq58EEQBIiIxpN3g3bnatXsvUmnnUEB1TRHEWyJTb/v37T9TUjBk9Oloc9VPI894cBQMdRSMa584/+Ve1Zh4FKJHHDIwxRFy8ePHAAQNSU1OjTeQnESL35z91LSv37d2nGjBECUrksYGU9L59+07U1BSOGBGd4kFEIYS9X5+k0aNqH38yWkKJhEfdhhgBEQAqV63q1bNn+3btoigabw0iEIEQ2TPvcq9a7dm2Q0Xm0UD0TRTFfyCEYIhHjx6tPnBg7Nix0WjET4GcCyEcQwbb+vWrn/0ywSnlKyKHEnkMINsYLl22rHevXu1yc6M0Gm+NENk/uKfl408Dx46rLSsRR4k82pGe+ZEjR6oPHCgtLaU2bWMYCmRknlQ4wj5ieP2zLyBjqvotsiiRxwBEtGz58k4dO7Zv186Mzmi8Naf7HN8z3fnZIv+Bg/J010gPK3GJ7umS8EgzXldXV1VVNX78eFnTGulBnRkZmaeMHW3p3q1h7qsnu6xEtwMSxyiRRzuMsYrKyvz8/LwuXWIgGpecTrP/8L7G198M1tQyzpXTHimUyKMXWeJWX1+/fceOsrIyEfXR+DcgoqTCEdae3WuffBoYI1Iee2RQIo9eZLF6+YoVHTt27JqXF6Vr498BMkZCMJste8Z056J/GfX1yBiIWHpIxQ0xM2kSDUHEGGtoaNi8devosrJYicZbg4wJ00ydcIWWndnw+lsnm5nHlDMSHyiRRy+MsVWrV+fm5EgzHunhfH9kmh0x+4f3N7zyqtncghqP9JgSESXyaISIGECL07l127bRZWUh70YcOhDJNFMuHK+3b1//0lxUh0lEAiXyaEQIgYxVrlqVmprap0+f2IrGW4OMCSGY1Zo+9brGN94K1tWfXE5ThJGYnDrxDRFxzt1u94YNG8aNGcNi0YC3Ajkn00y/diJqWsuH/5TNlSI9qMRCiTwaYYytrKhIS0vr3atXbC2b/SeyRxp3OLLundEw7zURCChjHmaUyKMLGXu3OJ3r1q8vHD4cGYvwicttBJlm+nWTSIjGt99TkXmYUSKPLmQBzKbNm5OSkgYPHhy70Xhr5JnN3OHIuuPWhjnzhNerGq2Ek5ifQPGEVLjP71+zZs2o0lLOOQHEgRkHAOCMhMiYep3Z2Nj0/kK1/zScKJFHF4yxdevWaZpWMGgQEcWFvgFOdVNiDkfmbbfUvfCSME0VmYcNJfJoQUbjXq931erVpSUlmqbFRzT+NYgkRMYt08jncy76FzJGqso1LCiRRwVEJEW+fsMGIcSAAQMi1Y04dMju5XpWRvr119Y9+7zw+wFBOe1hIK6mUUwj2xiuW7euqLDQbrfHaonbf4cxEiJr+h3GiRPOLxczzsFU6beQo0QeLSDi9h07AsFg4YgRMVmpfhac7HOcnpY+7cbafzxLQCoyDwNK5JFHuqxCiGXLlxcXFso2hpEeVCgRImPKtcFDR1o++wIZqsg81CiRRx65GL55y5ZAIDB8+HB5/Esc+uoAIE+GMk1Lxw5pEyc0zJ1PpikzEpEeVzyjRB5hZKW6YRgrVqwoGDTI4XDEZzTeGkQiyr5vhn/nbveadYxzUA0YQokSeeRBxF27dzc1N5eUlMS5ow4Apw6NsXTqmHr1lfJkKORqn3kIUSKPClasWFE4YkRKcnIiiBwAgEim2f27drtWVqLqphRKlMgjiYzGd+/e3dTSUlxUFN/ReGvk/lNr17ykMWW1Tz5Nhil9+EiPKz5RIo8YstyFiMpXriwYODA9PT3+o/HWIIIQOffN9G7a4t2yVW1ZCR1K5JHkZDfiEydGlZYmiqN+CnlojK1P75SLLqib/RIyBvFV4Rc9qMsaYb5asqRfv34pKSkx0zihDSEiIbLvm+FZUendtoMhkiqACwFK5JFBSvrQoUMN9fWjRo5MzHBU5tvs/fsllZXWPT0LGAMEVQDX5iiRRwAZezPGlq9Y0atXr9zc3PjbjnJWyCyjENn33u1auty7bQdTh8aEgMSbWNEBY+zwkSMHqqvHjhkjRAIXdiIKIvuggfYhBXXPvwiMneyjpmg7lMgjgHTOFy9e3Kdv36ysLCFErB/Jeu4gghAgRM6PHnAtXho4chQZUyJvW5TIw41cGz906FD1gQMlRUWRHk7kQcYEkaNohL1gYN3Ts06eDKV03nYokYcbGY2vWr26a15ep06d4uOoxvNCdlMCyH7gXudnn/urDyDniZmJDBGJPb3Cjky51dfV7amqGj9uXMx1Iw4Rcs08eWSxpWcP2U0p0iOKK9TVDCsyi75k2bKuXbooM/41iGAKECJrxl1Nb78XOHacqci87VAzLHwIIRjnNTU1e6qqRo8enXClL/8dzkiI5DFl1t69GubMA7Vlpe1QIg8fcuvJioqKnJycvLw8ZcZbI7spMas1+967mxd+FKypPdnPXHHeqEkWJmQ03tTcvHXr1jFlZYlWqX42yAK41Msv0zIzG159Q20ybyuUyMOEjMYrKio6dOjQo0cPlW/7FhDJNBEo58EHml5/02hqUlvT2gQl8nAgK9Wbm5u3bttWNmqUdE1VTP4tcE5CJI8bwzMy6ma/jGqTeVugRB4mOOerVq9OT0/v07t3glaqnwWISIKY1Zpx67SW9xcaLS3IuTLm54maaiFHStrtdq9Zu3bM6NEAoALy/wIyJCEypl6PuqV5wUeyHi7Sg4pt4kTkQoioVY4U+dLly9PS0rp3697mjjoRmaYZEbe21WWnNnshkGkyi5Z97/T652eTz8c4b8v3b7uXEIIoSmdda7RID6ANEEJoWvR+EcaY2+PZuXPnhePHWyx6KHx1zjkRhfnYiRBedmRAkDHx6sY5rzbOey1rxl1gmhB9yXZ5G6O/LyWaMV5yIKfa7t27Zz35fwcPH7HYHdG2uMoY83g8dfX1nTt1attMEiKapqmRMWXaLVddfQ1DDFs/c9MUuq7V1px46qmX169bl5bKzbbeL4u67t+xi/x+28D+RAIgWoSEiEDk9vALLhgz/e6bklPSDMOI5iRLbIvcNE1d1z/6cOFPH/pxu2Hj+oy7CjmDqOvqTYhMdlBo+3dmrPHQ/lVvzZp86fi/PfkUEIXhvFf5YN28adP0u+7Nyd560w3WtDQyDWjjjyVCqwUQyR8ABIiawJwAEKGxEV573QA2dt6rs9q162CaZtTqPIZFLivGdu7cMfnqiYV3/aLoujuFAIqeufANiNpaBAAACMB1rK3aPe+H102/cdIvH/ldqL1HedlbWpquvuqGouGr//Rohq4HQhUoSK8n+pxhIuA6NDdot99Vz7QJr77+kq7rUXucdqyKXDb01jTtlhumHtGyJ//2GVdTE5AAxKiVeduDAARCmEnp2Qc2lH/2uxkffPB+7z59QmpVTNPUNO0fTzz38Ue/WLggPRgIBIOImDgX/SRCgMOBLpd2xQTnT38+e+rUyYZh8OhLHEDsJt6kx7h106btVfsv/f0jfq8XgJDH6tc5Hzjn3paG/GFlmf2LXp378h/+8ljomjTIB2sg4Ht1/hu/+JnVohseD2hawikcADgHr5dycsTNN+Jr89+ZOnWiTH9GoTGP0ijijMiVm/Lly4JJme269wn6fcii8SEaJhCJzLzho7ft2On1+UK31iCzhlu37rHoVUOG6D4f8VidQW0AIgQCoqzMeuzoptrahiiUtyQmbxERccYA4ED1/uzu/QEwelKvkQGZGTQ69R3S0NjU2NAQumpQ+bYbN+zIz6d27SAYTOjLjgjBIOS2w6wsV9Weg3Dq+kQbMSlygJPJmGAgmNauU6SHEnkQQAiRnJXb1NTc3NQEIZ5tXm8wLVXYk8E0o3FOhw1EMAxITaGMdBbNqa2YFfkpLEkpCW7FT0MkDMMITyZV0wA5QTRmvsPKqcNmo/phF/Mij7bSl4iCYVvFiUq3NDJE/2Mu5kWuaE10xoSKyKJErlDEOUrkCkWco0SuUMQ5iVgi9n0hIb6xPQKRfd98CwkBCIjqqfr9ON2wHAEQz3DVZRI2WveJRAwl8jOj2+yte3oggBEICGF8jwocIt1mJyIz4I+BbGzUgIhJjpMXjAgCATKM75Q6EVitiAiBgMo+/htK5N8NESAK0ziyc6fh98lNGAhAJLI6d7enZpAwz0qxREyzHN+zjWl6TteeZjCgdH5GiIAxDAZp0xaTiASB3Yr5+TwjHX0+EvTN5ysRcI77q01/AHp0YyA3hEZk6NGHEvl3QgCcM2+z861fz2g8dtBiTxLCZIwFfb6bHn2x75jLA54AMia3i8PJ5SsCwK/dciIiEoaRlJG88LGHU7Jz73r6jaYTHq7pEf5usYCmYU2NuPq6Zl0HxkDXkUyYdqPtN//PIYJEAHRqXzECEEGSA599wVu1z3zzlVQ4+ZhQj1MAJfIzgQTkbqwdetn1Qy+/zuNsYZyToA59CgDAlpyCjCHjAY+bSFjtSYwzIjD8PiPgJwCuabrVDgSOVBbwuv1uZwJuyTxnEAkQmhrEH3+fPGyo5vPRF18GHvu7u0d3ftedtqYGkZKCFh0BwTDI5SIEcnvI46HUVOQ6Gn7y+sA0SelcifwMICIylj+kZMTVFzsbgGtgBMA0jH1rlx/ZudnnbqneWHHVQ49mdu726VO/rVq9JLNj3pjbftSh5wAg8jqbP3vm93tXLx1+9U2GEeSaRdWqfC8YA0S66EJLcakFgCZdZ3v7Pf+qNcG777Uzhu8v8M9/w+/10pTJ1qnX2wiRMzRM/NNjnk8XBS4ab7lnhj0lGQ2DEjwVp0R+JogA8fD2DRsX9fK6WkBQUmZ2tyGFR3Zs/ODPP87t0S+jfWefq2XeT6Yd2b6h+Lo7juzY9Pz0y6c/uyBv4LBXfjqtdv+uERNuXv/xW0e2re/UpyAWzvaMIoiACJcsDTidIhiAZSsCnMO1k6wiQLNf9v78/7mmTLH16skffNi1bGXw9XmpdgdUrgwEfHTBhZbnZvvKK4IfvpvGmGxlEekvEzmUyM8AEXBNr3z35U1fLEAkv9s17MobexYWEYAtJW3q75/rWzam4q35VauX3PX0+wUXX+qqdz1x0+g1H74a8Pn2rlryg1eXFFw89sjOg/97XXHQ71UraN8LYQJyeOZ5b1ISGkGo2mP06s379uJ1J8T/Pe29e7r9hRdSALF/P+3+B50P3m9YdMxtx959PbVbH33cKP2qic1LlgYvudjidiuRK74bRDCN4Mjr7xp25VSvy0lCJGfmCBNMI+hIz8ju0kOY1HD0AAB88uRvFj72U023Nh6pTkrPajlxGBA79ik4sa82Jz8vq3P3oM+TyFPtHGAcyKS//CF5bJleWyeqD4j7H2x56GeuR3+XfOK4OfU6m7eFfD4aM0pPScbqA6YQMHyY3q4da6ox+/bh3XvybTuNKy5P9ChJifxMIAJRux79+owqdTX4mKYbfi8RyFUa0wgiEQlhS0opue4urumI4Pe4c7v1bqk9Ll19xnUgiKpDhWMFRADAnBzWqQtPSsYhhZbKtcG583zHT5hWO/r8xDloOpjm17l0r49MEyw6AIBhkNWCCa5wUGWtZ4nh9/ndht/j9LtbggHf6a2WDJlhQE7XXs7G2pTsdhfPvGPolTeu//StA5tXt+vRj2na2o9ey+qcXr1xw/F9O6yOZNXx5xxABEBAhK0bAm+97e+ezwcN0Hp040896wGClEx88x2fx0sDBmiIuG5d8OAh4cjg//oqcLDaLCnWg8GE9tVBWfKzQZgGASDTkHFkHIkAGBEJ00DO/B7PwAuuKp502ysPTf1y9rCGoweCfu8lM3+RP3jouDseWvCXn6xd8Irf6/G7nIAAQj1Vzx40DQCEm+9odjhQmNDsJIcdf/KgPbs9/8XDSTPvb+k3rCEjnVXtMX7+46R+/bnHI3xemji1OSMNt20zfvpjx+CBms+nsuuK7wABSAiLPem6Xz+Tk9/L7/XKc44ZY363t+/oy3K79dZtDhImMj7pF0/0Kb3kxL4dFlvSgAuuatetj6fZdfkDv80bVHx0x8Yug0ZwTdetNp/by6Ly1N4oJBik1DR8bW6qPwAkgIBsNiwt1jt1ZM315tRrLT26p3/xZSAQhLLfJo0do7uaadpU2+SJ1rpasX2H8dMHHVddYQkEKYraMkQIJfLvBpGINIt10MWTjIDfDPhBJseRGcFAu259OvYpCHhcRCRMExCHXXmDbgUS4HV5fS4nMmYEg0MumVx49bUBHwEJEuT3utUelbMBEQSR3YY3TrV97WwTuNzk9hDn0OKioYO1klE6IBhucroIERJsS2gAACAASURBVIoLNWSgaYhWIB80t8hNQZH8ItGAEvkZICJvSxMybC1ORAwGfAHfKbOMCESe5gYiQgBkXG5oQURPSxM1C/l/ESGhz43+niCAENTQQK3/xNjJTWacgcdDTicBAGMnuyG6PUR0Mst5+o8KJfIz860ONiJD/u+/f1trB8Y5gJpr5wgi/Jcj5E8LvvVfTqIueSuU66hQxDlK5ApFnKNErlDEOUrkCkWco0SuUMQ5sS1yhCht+x7nqEseU8S2yAWIgNsV6VFEEYyxMDz1SJDc6R3qD4oNCKL8sRerIpf9gKw2W/PxQ6oxFwAgY+6m+qyszPSMDAAIqdRTUmw1taylATQt0a895+D2oNNFXItencekyE/33+7WrVvDgd2qcJGINF0/um19RlpaZmYmEYVI5AwRAAYP6Xf4MK+vA11P6OZrQoBFhyNHqbbW0aNHl0gP5zuJSZHDKUtVVFLKnLU1+3ZqViuJKO4QHWqEQIR9q78aPGigzWYzDCNUlhwRAPr27RY0u2/aHLRYWCI3lSUCTWcVFYEOHYbm5obw2XqexKrIOedCiMFDhw7u27N8/j9sDjsAkDCJRKK9RDDgyMjcv6a8ZfeGG2+9VQjBQrm10jAMuz3p5ltufPpZXyCgWSxoGEAk23Qn0MswwOHAmlp87XVx6+3XAzDTNKNT5BienvWhQAjBOd+1c+fkq68edtvDJTfMMEwTQtIOHokEATBk0bZvkYB0q35i1/ZXH5o68+Yp//OrXxuGEVKRCyEQsaGh/vprbxo8aN3f/pqmacIwQnowA4LsVMX497n+MqYLiXUlAosFG5vwjjsaNeuE1998iXMdQpwKOWdiWOQAIITQNO3zzz778UMPpfQe3mPUpbbkNGrbI1HlhlNN45z7/X5EjKJcE6Iwgsd2bNzz1QfXXHrBo4/9TeM8DAl2edm3bds6/c77UpM3T5pIHTvAf3Y1aRsQSAhms6GmCbf77PPYBKRrOjIMBALY1kMThPv20YKFmJI2bs7cZ3PbdTBNM6TP1vMhtkUuO5Romr5nz+65s2cfPHSYc05tamylwmtr65qbm3v26G6YInoe1ohomkLneMVVE66begMRSTMbho+WOm+or3tu1ivbt29hjEKVgiNCi+7fu9+sqXWUFIFhnOXHaJwfrznh9/m7dOkihMC298H0wsIRM+693Wa1h9p7Ok9iW+QSOeHkz2071WQqBRFnv/RSt/z8iy68MGwqOkuISE4vmWwL59j+/bKH5phKItnfcN+ESamXXprzwD3CNPEs5CQvy4GDB95+5907brstKyuLSLThcR2nLzsRRbMNl8TDfnLGmGEY8rq37SwXRBxx+/btDQ0N0268UQgRhUtG8rvzsJ+QwBgzTdM0Tc45YggsJQCZJtO1pgUfBmvq0m+5UZimrMI5m/9rmmbXvK7t2rVbXl4+aeJE0yTG2nKEhmHIrFCUKxziQ+QAcPqx2sYiJDJNc/HSpQMHDLDbT3pl0aZzRIzUPENETdPa/rJLiACRgkbtM8+lXTuJp6WJQAA5P8vPkj7XuLFj57/66pjRozMyMtrWC5Pfva3eLaTExijPkrY146YQnLE9VVXNzc0lJSWh8BTigxBdEzJNpmnNny4yjh7PuuUmME086TKcFfJx3Lljx/bt2y9euvS6yZOFEKEbbTQT7Z5GpCAihsgYW7V69YD+/bNCWUam+BaIkHNirGHO/PTrJ1s6tKfvaYdlWSQyVjZq1K5du2rr6qLQCwsPSuTfCWOs+sCBw4cPjx49WiRyYVckkPp0LSv3V+3NuvduIcQ5FC9LVffp3TsnJ2fDhg0J64gpkX87Ms5cvGTJoIEDM9LToy2pHucQAQAJUfuPZ9MmX2Np147OLqn+nwghhBDjx41bt3690+U6veshoVAi/xZkZej+6uojR4+WFBdHejgJB5mCMeZavsK/Y2fWnbfROZlxiVR1t/z8nJyc8vJyxlgCOmVK5N9Ext6MsYqKih7duuXk5IS6GlzxbxAhZ8BYw0tzUy66wNK5EwlxbmYcTomccz5q5MjNW7Y0NTXxs87Pxw1q7n4LjLHjx48fPHRo3Nix0bk2HsfIaNy7Zat30+bsB+4BIc6zjhgRhRC9e/e22Wzr169PwPSbEvk3kTNgybJlPbp3b9++vTLj4YaAiGqeeDr5gvG2nj2EaeL51flIY84YGzd27Lr16wOBQKLd0MT6tmdE1jAdO3asev/+0aNHR3o4CQcZBuPMu3mrp6Iy+/6ZBNAmJ4JIY963Tx+Hw1FRWSl/Pf+3jRWUyP8NRATEFStXdunSpWOHDsqMhxUi5BwYq3v2eUfhcFuvnuecVP8G0phbrdaRI0euW7fO6/UmlNOuZvDXyJRbTU3Njp07S0eOTKiHfTRARIDorz7gLl+Z86MfnH803hppvQcXFGi6vn7jRiXyBEVGbpUVFXl5efn5+YkzCaIHZKz2qWcdxSMcQwrEeSTVv+WdEaVfVlxUVF5e7k+kyDxRvucZkTOgobFx1+7dZaWlcMqwR3pciYL0zH379ru+XJL9wH0nQ/G2vv5CiEGDBlkslvUbNiROZK5E/jUMsaKiIis7u2fPnioaDzeIyFj98y/a+vdNGj70fNbGvwvpojvs9qLCwnXr1skd+Ingr6l5DHDKUW9uadm0efP4sWMT4cZHF4KQscCx4y0ffpw5/Q4QgkJjY6X1Lios9Pl8W7ZuTZDIXIkc4JTIly5blpmZmZeXJxLgxkcVRAIZa3h5rrV/3+RxY0hQm5txiRS5ruujRo5cXl4e/Ye6tAnx/w3PiPTMm5ubt2/fXjpyJOf8++5qVJwPZApkLHj8RPOCj7JnTmeIROderH5Wn0g0aNCgQCCwcdOmRIjMlcgBABhjGzZsSElNHTRwoIrGwwoRACDnDfNe0zt2SLnkorZNqv8nco9KUnJywaBBq9askcY8vp32RJ/N0lH3er2r1qwZP3YstPVRkIozgpwFGxob5szLmjkdZZeGELtRiEhCjCotdba07N23L+7Tb0rkxBhbUVGRnpbWu3dvoZbNwovMoje8NFfr1CF57Ojw7NuXLnpycvLwYcOWLFkC8X4mVEKLXCq8xencuGFDUVGRisbDjFS40djY/NHHWdPv5ElJIASEK1YSQhQVFbU4nTt37ozvfeaJLnJE3LhxIzI2aOBAVf0SboiQ86b3FyJjGddfG4q18e9CqjotNbV/v37lK1ZEbRuzNiFxRS7NuGmaa9auHTt6tOygGMd3OuogQs5Nj6f+hZezH7gXGZJphrMLtXTaR44cefTYsf3798dxmj3RRb5m7Vpd1wcMGKAUHmbINBGxYf4bqOupl1x4Pmc8nRtS1ZkZGUOHDFm2fHkcH/OYoCI/nVRfvWZN0YgRdrtd+ephhQg4Fz5f87vvZ9xwPU9NDaev3hohRElxcW1dXXV1dbxG5okrckTcum2bEQwOHz5cmfEwQ7IA6dPPRUtL5p23RkrhUtW5ubm9e/VaXl4up0H8LaclosilGRemuWTp0qKiIk3TlMjDjOx2VPf0rMzpd3CHI8zR+L+NBFEIMW7cuIOHDh09ejQuC2MSVOSIuHnLFgQYOmSIctTDjIzGG995j1yu9GsnhT8a/+Z4iDIzMnr36vXl4sVh7gwbHhJO5FLSpmlWrl49bNiw5ORkZcbDChEyJvz+hpfnpVx9pZaZ0VZnPJ0b0j8XQhQXFx89evTY8ePx57EnosgZYzt37XI6nSNLSpTCw4zcYeaqWGXU1GTfd0+kovHWSBc9r0uXvLy8lStXSpHHk84TTuRy88mSpUuLCgvtdrsSeZhBhoBQ98RT6VOv1zMzIhiNfwMhxAXjx+/ctauuri7OdijF1Zc5I1LSW7ZudblcQ4cMicv1kmhGeuYtX3wVPHos6/abyTQjPaKvIaIO7dv36N598ZIlSuSxiozGiWjVqlUD+vdPS0tTu0rDiozGTbP+uRdTLrnI0r49CXGejRPaitMueklxcdXevTIyjxsbkEBTXIp8f3V1XX39mLIy5aiHGbn5x7t+g3fr1qy77zq3bsShQ+o8Pz8/Jzu7srJSPv3jIzJPIJHLNoZLly4tGDgwLT1drZyFG0RgrG7W7LSrJ1jz86Ih5daa08b8wgsu2LlrV3Nzc9x4eXHyNc6I9Mz37t1bW1tbWlqq2hiGGTJN5Ny9fr13w6asmXdRmzZOaCuki57ftWu73NzlK1YokccY8v4tXb68V8+eGRkZKhoPK1LPRPXPvJA8brStZw867zaGoUAac2RsdFnZ9m3bGhsb42PNPCEmugy/Dxw8eOjQoTIVjYcdEoJx7t2y1bl0WdY9d4fhgKdzRhqDXr16paWlVa5aJZfQY13nCSFyGY1XVlb279cvNzdXRePh5lQ0njxujL1vn2g+fkcOjIhGlZau37ChpaUlDjy+mP8CZ0R65kePHj1w8GDZqFEqGg8z0jP3Ve31VK7OvncmyOsfrSKXEFHfvn3T09PXrVunRB4bENGy5cu7d+vWvn17FY1HAIK6WS/YhxQkDRsiojIab4302DnnZaWl6zZs8Ho8sR6Zx/l0l3fr+PHje/ftGzduHMT7uZzRhix38e/f7/z4s5yHfgDQ9j0MQ4HUef/+/e022+q1a5XIoxq5c3DpsmV5Xbq0y81VKbfwwxirnzXbNqi/vWBQNEfjrZGD1DRtdFnZ6tWrvV5vTO8zj2eRS8+8tq5u3/79o1Q0HnakpP1HjzkXL826Z4bc0hkTllxCRP369dN0fc3atTEd4sXw0M+SioqKzh075ufny02mkR5OIkGEnNe//IqlS+eU8WPlEnSkx3S2yEMHNE0rKS5etXq13++PXac9Zi7690Wa8cbGxq3bto0dNw7jpQ45VpDReLC2rvnd93N+/MOTCokdMw6nToAbOmSIruubt2xRIo865Nr4svLyzp0753ftqqLxcEOEjNU9+4LeuXPyqJJYicZbIwdss9lKSkpWrlxpGEaMRubxKXJZ7lJfX79t27aSoiIZjcfcJItdTvY/qq1t/mBB1p23IuPRczjE90UIMXzoUCLauGlTjIZ7MTno/w4RCSLGWMWqVRkZGT179lQKDzdCIOcNb7+n5eakXTNBRM2+8e+LjMx1XR8+fPiKlSv9fj/EYNwXhyIHAM6Yy+Xavn37+LFjT+46UCIPFyQEaprZ4myc93r2/TORMYi1aLw10kUfNnSo1+vdvmNHLDZgiE+RM8YqKivTUlP79OmjFB5uiJCxhvmv8Yz01Msvi/VsiDQSSUlJRYWFq1avBiLOeWwZ83gTuZS00+ncuGnT6LIyWboU05MstpDrZEZTc8Pc+RnTpjJdh5iNxlsjhCguKmppadmxc2fMpdnjSuRyVyBjrHLVKrvd3q9fP6XwcGOayFjzwn+irqddM4GEgNiMxlsjTUVSUtKwoUOXlZcbhhFbkyquRA4AjDG3271u/fqS4mI4ZdgjPaiEgQg4N/3+hvmvZdxxqybbGMbF9ZfWe2RJSXNz8549e2IrMo83kSPi5s2bbTbb4IICpfAwIw+HaPnwY/J6Mm+cGltFrP+d08Z8QP/+S5ctO33yb6THdVbEj8jldQ8GgxWVlWWjRqk2huFGdiMOBOpmvZB52y08OYkMI4bqWM8GIUTpyJH1DQ3VBw7EUGFM/NwDKem169ZxXR80cKBSeJgh02SIzR9+bDQ2pl0zgUwT4kvh0kXPyMgoKChYFlPGPE5uAxFxzv1+f2VlZWlJicViUb56WCFCzkmIhvmvZ0y5Tm+XG20nLrcJUtVlpaXHjh8/EDvGPH5uAyJu2rQpEAwWDBqkFB5m5MqZc/HS4MFD2ffcHU/ReGtkZJ6ZmTlwwICly5bBqVKZSI/rDMSPyImofOXK0pEjrVar8tXDinRchah78pmMG6dEvBtxqBFCjCwpOXL0aPWBA5Eey1kRD3dC7irdtGULAAwfNkwpPMyQKRCx5fMv/QcPZd52c7yacYn02LOzs3v26LG8vDwmzmyOeZHL6hfTMFauXDl82LCkpCTlq4cVIuSMGGuYMy/1koviNRo/jRS5EKJs1KhjR48eO3Ys+j32eLgZiLh9506Px1NSXBxDJQrxgYzGPevW+3bszP7BvZQA11+qulOnTnl5edKYR3maPR5ELoRYsnTpsKFDrTabaZrKjIcVIiKqefzJ1Csvs3bpHN/R+GmkMR83dmzV3r0nTpxQIg8hpmkyxrZt3+5yuYYPG0bqTPXwQobBOHevXuvfsTP73rujeaK3LYgoiDp06NClS5evFi+O8j7HMSyJ0wczrlmzZsjgwemqG3GYkQczItY/+7yjuMjatSvF7OEQ3xc5zYQQI0eOrNq7N8oj8xgWOQDIbsQ1tbVlpaUqGg8zMhr37trjWlmZ84N7QQiI0kkeEhgiEfXs3r1D+/Zr162TkXmkB/XtxLDICYCIFi9dOmTw4JTUVLVyFm6IgLG6p2elXnSBvV9fYZrIEuv6y8j8wgsv3LJ1a1NTU9RG5rEqclMIztieqqra2trSkSOVox5mZBtD745d7vIVWffNJESQr0RCqjqvS5cOHTosW748aj32mBQ5ETFEAChfsaJ3795paWlK5GGFSB55Xf/8bPuIYY6CgfG9Nv5dyCnHGBszevT2HTvq6+ujU+exemMYY0eOHDl27NjYMWNUNB5mZDTuq9rX8smi7BnTQQiIvpkdHmQ1e4/u3VNSUlatXh2dizvROKYzIh+WS5Yu7devX3ZWlorGww0RY6xhzlz78KGOEcPi5viXc0MeAT5+3LgNGzd6orLPceyJXHYjPnz48KHDh0ePGhXp4SQcstzFf/iIc9EX2TOnx2L/o7ZFbs7p1bNnVlbWyooKjD6PPfZELo3G8vLy3j175ubmClUAE2YQkfOGOa9YunVLGTcmcdbGvwv5mNN1fVRp6YaNG10uV7RF5jEmD5lgO3rs2J69e092I470kBILImQsWFvb8Oqb2ffNlItIkR5T5JGNVgb075/kcKxbu1aJ/LyQVW7l5eU9unXLzc0losR1EyOBzKLXPzfb0r2bY2RxYibV/5PTXXpKS0tXVlZ6vd6o8i6jaChnRHrmdXV11dXVZaNGqf5HYUZKOlhX1/LpF9kz7uJWa3xvHf++CCH69unjcDhkmj16Fn1iSeSIiIjlK1a079AhPz9fReNhhQgAkPOmt95lDkfaxBhuYxgKpItus9lGFhdv2rTJ7/fL1bVIjwsghkQujXZjY+P2HTsuGDcuqmKeBAEZM53O+jnzch56QO7PiPSIogup6uHDhwuijZs28ah5AsaSyBlji5cs6dC+fedOnaLkGZk4kCBkrP7FuTwtLXn8WKEc9f9AipxzXlZaumLlymAwGCWeptb6FzpFpEbzXUjPvKamZtv27ZMmTjRMs819dTxFG75nG/L1rYnEorQsdzGcrvp3P8i8dRpYLGYggJoGphmGTz+3WyN3j4RoSN+FEEIIMWDAgOXl5atXry4pKTEMI/xS/8YV+1rkUjbR42P8Jzt37+7Vu/eggQND9xERuSVnJEpujbFwYXaqI3fmXQAAmnamf97Wn/59bo0QQtO0SF0xi8Uy/oIL1qxdO2rUqEiNwTTN02lpNE0TTl0UAFixbNmKpV95fT6GGDUW/WSrinXr13fu3Ll9+/YkBEBbWjNk2H9gwYWXXp6enhZtOpd9IwDEksWVK1asdzmdjLNw3xoEJGj+YKGWm5s0poxMo22v/7d/JgIRWXRL/4E9L7tsTGpq+tncGunvaJpWW1u76J8f7t9bFfZpTIjo9/tXr11bMHBQenqaaOvp+l3IK5aSmlo2/sLComIAkKehoWmaMpA4cuTIww/+cNOeA9m9CkzTjDa3lQB0XSNBZtu7iMS45qo5rLnq/vfJJ8tGj4kencuH76GD1ffMfLi5aUXvnoYgkygsU6Y1CECAVgsAkt8vfw3DhxKBpvED1djk7Dnruf8rLCoygkH23bbxtMLfe+ftR//wRy23qzUti4QZHo21BhE1XTOCBgGF9SwNBCSqr9o6unDIX//3idTUFCEEBgIBxrCpqWXKxKudaZ2vevixjM55GBUz/JvIR3LbB6QEgOBpaF719gs7Frw4d968oqLioBGMuHt8qi6g5pqrbujbe8Ojf0zt2IkggoMK1Q347x8K9TX40hzv62+0f2nOvGHDh8qD/b7138pn4gfvvffQQw+Nue93g6+4wZpil/c3zETkUslvKgyo3bvzg9/dNyQv+4W5r1gtFgwEArqu/+yhHy1at+u2Z94nZAGPO+ESp0Rc0x3pqZ/8/VfBbcs+WvS5rusI4b9LrUdERMQY/vzh3+zY/o8F72UHAgGPN/zTNfJoGqXl6P/vZ83rN16w8KPXNU0/fbxfa+Qz8fiJE5dfdOGgGx8smTbDVd9Ewky4yQxgTUr1N9W9NOOKh+6+5f4fPYSmEAer90+aOHnMT/63W9FYb0sT0/RIDzICkDAZ52Qar9434ZGfPHDtlBsMw4igMZcx1L69+yZcefkrL7sHFaDHLSLtW0QG0wRNA79PmzDR/9s/vHbpZRd+qzE3DMNisTzxt8fmLyq/5al3fG4PIGJ0OqWhhUQw6MjIXv/B3OoPX/jk8y8YAnzx6aeQ1i5/xGify8nCnjWNEpBxYRiOjMz2BaO++teXMi0Z8dXEJUsqe3Sv7duH+30iOrIEEYBzMAzIzBGXXGK8996ib70p8pkYCARWrlzZY9QlyC0AkJAKBwBkmu53u3qPvrwpAKsrVjAA2LFjR0aPgfykvBPOt/kaxgx/MH9Y6cHDh51Op6ZpERd5RcXGEcO5I5UMIwG9zn8DAXr3xv17NzPGvvVSMMaOHjmyt7q6Z9E4w+9PVIUDAACiMIKpue14Rvuq3XsYAPj9vszO+ZTwuzYRkIjSO3cLBo1AIBDhwSACQHNTTYf2wFjC3xoEIwBdOiNjTU6nC/Hb93IG/H5rWrY1JZ0o4QsiEckUye06+/x++bRj1uS0RDbhrWFci54ztJOTIT2dIOHNOAAAEiLz+wP1dY3/5e5ouiWcg4pqEHWb/XTQQiTCUZ8YK0TcSz+NEGBGYJU3aiFE5Py/+eHRc++iAXk1Tl8vNY+iFGXDW6M0fA4kcHJCoUgMlMgVijhHiVyhiHPCLXIiQd9ouBGVO9gTASG+2fuECISAs19LTeDWKUBEJAR9cyaLUz9E0XUJa30bkdCtdmTMDAbEye2KxHULIhrBCK9LJxqI4LAjIAQCYJqEKJuUgs2KQoA/cFZz1GFHw4RgkBIuO0ik6RamaWYwKIyg3OTJdR0ZN/w+zWpDxoJeT5RkTcNnyUkIqyP5o8f/589X9D+8fYOmW4Uwdavtk3/85q1H7pGlyCRMEkK+5G7GUz+ffAdV5HD+EAHnWFNL4y5vKihsOHjItFjRMMFmZcePU8m4psk3tvgDAIimedLayxecNvVC1pPjJ58HvloStFjQNL826fLfxDHCMBypKUvn/+PPl/fbWb7ImpRkBgP21OTFLz/+8g+vtTgcnz3929d+fqtus8vjaVpNaYDTLoB8hcXgh0vkREzTm44d3rbkn3UHqla8MUu32UCYiKzp2KGGw/sBkISw2B22lFRbSprVkSS/vjUpRbfZ5bFHFkeSxZ4UpgHHNYgQDNDOXebuXcZHnwQsOgoTdA0q1wQ3rA9UHzCFCUBgt2NaKktNxZQUtFqRCHQdk5MwyYFpqehwsL887tm5x3SkM4cDdf3kKSOMYUoKYhQdOtKmCKFZLE01NZs+f6/+8L7K914K+gOIDBlrrj1Wd6DKCAR6jBgzYPwE0zCIyGJPsqWk2lJSLY4k6cZzTbMlp8oX5zwMditM7rowzeS0tPLXnkZkY2774cZP3j5etT2zUz4JoVmsmtVGJKyOpCO7Nq//5+s+t3Po5VN6jhjraqxbu3Bex76D8wYWmmZw61cLAx53wcWToyrgiVEEQW4OA4JPPw889AMH5xg04b0FAZuDp6YyQWC14rbtxgcL/QcOi769+eRrrN3y+eatwb37hNdL23caHTvwxkZavtzfqzt3ukSf3nzQAD0YpOYWmve6f+JV1vR0NIx48+QJSLfadyz/rGbfzisf/OOnT//+2O4tHXoNBAJNt+g2BwmRmtPelpxKQuh2+6Fta9d//CYJUXDxxG5DRwnT8HtcFW/PPrRtXd7AwuETbrTYk41gaCvtw2LJiRjX/B739qWfZHXpful9v3Y11W3510Ldape7poURtCXZN/9rwT+mjT64da2nuXHWnZcumf9EevvsrYv/Ofueq33uln1rl835wfV1B/fqVlucu4OhBwEQIOCnKy+zHDkqKlYFU9Jx81aj+oA5epTu8ZLDgf/6KlBU1vDV0iBj8Pf/81w5uVkArVxl3HRL849/7nrvA/+iLwJ+P+3bL5qaxB/+4nn8CS/XwW7H2XO8v3vUIwQhxGVaDgFx7YevduxTUDjxttSc9ivenGVNShICiEiYhsXuWPn2C588+euk9OT1/3z9qVvG1lTvqj+8/5nbLlr38ZsAMOuOS7588TGLPWnxnMdffGBywOtmXAvplQqHyIlIt9mO7NxcvXn1pff+qkv/7OLJd6xa8Iq7qY7rOpFgmuZ1uxfN+mO/0Zf/6NWlM55757IfPPL5rD/V7N9782NzNIv1jV9OX/jYz/qUXXLp/b8J+r1Rks+IaRgHp5suGGdhCF8uDug29v5Cf1YWGzVS97gJATZsMm6ZZl+5MuOVV9KeeTJl/35zb5WZlorI4JknUzatyXz39dRu+fy2m223T3fceL1tybLgoYMm6vDam74pky15edwXgHjbHkuk6Zb6w/t2r1o86oZ7+o7qVHjNLTuWL6qp3qNbT1bjEZFutdtTM3xu76JZjxZcNOm+lz+b8fxHhRNvPbpr04q3nq8/Wn3/3C9v/ftz97606OCWNRsXvWORAWnICI+7TozzLV8uMP2+qjvOEgAAC0RJREFU5a8+s2bB3GO7t9Xu23Vwy5oB4y8jITSLrf7gflfdCcbYc3dfKYQR9HkNv6fu0MFBF15y459eemHGVWkdOt8ze7YR8JMQkMi7CNsOISA5GaZca/1kUeBnD4sVK4MXXagnOVAQ+f30y585vlwcmDnTWVNj7q4ybTYkAq+X2nXghcM0uw3dbmEYFDTIDIqp11n//Jh7+w7j6DFRX0/XTLAGg4BhPdwsHAjTdKSnbX79A7/Luf6Tt/ZvWFqzb6+z9njVqiX5BT1OR9ckBNf0xiOHTL+//9grhSE8LU3XP/JMak7y7Hunabp14WMPGwEf1yyaZtm3trz0+hkhHXYY1EKMaZ6WxvWfvNV5wDCu85b62uy8HkmZ2SvfekHTGZFARDMYNIL+dt37dhtW2mVgYe/Si6948NGszvlGEFpqjwNAwONy1tcwzuPRA4wQBMLEKdfadleZn3/u37vfvONmu8dDCGCz4R//6plwbfPGTcHevbTrJlmBAQEQgd2GiCeXzRCRc6Qgdc3jF19seXGu76NPAtlZOH6sxeWKu3NsiLimuxrqt371YXZe96T0zJYTtentO2fn91z1wRyfGxnXvt4ehyCESacOGkZEb0vTkZ37gn6fIy0jf0hx/pCRXQuKLrz7ZwUXTzIC/pDuegy5JRemmZSRuu6jf7rqa27+6/yB40Z7ms3kLP7mr/5n+RvPnth3wJ6S7mlpys3vmZbbkWn61Q//UtNh5TsLVrz5/PCrbqqtrvrgTw+NnHp3bfXuN341/aE3V3JNMw1DNdM8f3Qd/QHq1ZMPHqg9/HPXgH68SzcWDJLFisEgvf6W77JLLQsWZADArKfcQR/ZbYh48sIjykoY8vqAM7Tb4NqJ1vsfdFauDv70QQdiHD6JiYTFkXRs85bqDRW3PfFW8aRrfS6ypeDil19469czj+3ZY7UnyavDOCfTzOjYmeuWXRX/Kr72lpSsjLmP/shZd6JDrwHVmypLp8zo0Kfd8T118392c1aX7kzjRjAQOp2HWuTEOA94vEvn/yMlq123ISX1h+sBwAjYhl0x5cvZf13+2tNBv9dVd9yeljrm5h++87v7Go8ezOrcbfX7c4deMQURZ99ztSM949pf/ePEvl1/u2bIW7+ZecMfZgvThIicwRk/oBBQUyuam8mexkpLtL897r33nnTkrKmJamoEYzhqpP7yHO+PftByvEYsWRY0Ddq9xwwE6ESNEAKIkHHISGe/+73L56Pf/dJx8XhL1y58/wFzwhXWYDDS3y8kIAIseeUJa3JKj+FlzSdajGAg6LP3LBrHdP3z5/6QnJ7jrK9BQL/H5WyodaSlXHrfr9/+zUx3Y73FZt+46L0bHn1x4LirNv9rwZ8nDBpy6bW7VnzRfOLYpff9JtSLaCEWOQHj3O92lU6Zkdmxq2kEGdcA0TTNnPze0/76iiMtg1usBRdP9jrdRZNvy+jUdVf5ooDXM+UPz4+48iZPS+PIKXf3LB4nTJGT13Pm7E8ajlQH/V7GuVpFOx9MkzIy2IvPpgwfqnlaxC032Xr00MaP1T0tYsp11qJCjTF49LdJPbrzPVVmj+78R/c79lcbOdmY10XP+N/k9DQMGqRx+NXPHb26s655DBC79OBZWax3b969O3e7KP7SJshY0O8feMHVRZPv0G0OIuK6bhpGWm7H2x5/nYiSM3PzCoqCAf/wq27yuV2eJveICdOSM3N3Lv+MiKbPWtCv7FJhintfXLT+kzebjh0cctn1I66+OTuvp+H3IYtddx1RmKZus4+8/g4jYPg97tM+iTDN4sm3CpOIBCLzuZ1Bv6/vqEv6jb6MhGCc+VxOR1rmRTMe8rn8Qb8XAfuWXapZmLupRXbRDe3I4xdEMImSk/CuO20+N/m8omcPPmiw5m6hgFcUF2qjR+lNTSI5GX/xU4cQwHUI+Km0RPP7SQgoKNBamkkQBYMwpEAbPjRFEO2vNldW+jZvMZ5/OoVzEERxeR6oMI3CiTcLQ/jdTkAEQEAQpjn40usQwDQNrmneluZuQ0chZ36X0zSC/cdcPmDclQBAQvjcTgBK79D5svt/LUwTGTcC/qDfG+rj6EJ/LxCJyNXQgIjIeOu/uxobTh2KCoxzROZ1NsvmTUSCMU4gWmrqkXEZ6nidzbLbScjHHO8ggGlSfS0xBoyBz0duD2kckIHbTU4naRoYBjU2naxph5NdZQEAPB7i/OQM93jJNCk1FV+c6/v74+7rr7dNuMLibCEtzlJup0H8/+2dXWwUVRTHz7kzOzvb3Uqs0o9tKlHbtRGiQOEBwgtfKoTYBA0kBhTwSR8ImtjwIAhoMRJNQA1EYoPRiA+KkTTgV3jQojaxDwWhTastAaUl3W6h3W47Ozv3Hh/utrR2i22Qzrpzf5mHzewkOzvn/GfOPXPvOYnrfQA4rosL4lB/n6zKR+kpIfERl8YRl047OQA6yWTKskYTcjOQXZohwWRU5uhOvLlHG9mT/udji8Dfoj+OYrog3uxZKKX+j8+IkPF6j/VJxgARkknY/oK5Yb3xUESXN4Q7eN5uMxVPRqZlcuk0yNKh+YzFouqpqLgtENMj/NmzWTJJpNqWZx9K5IrbBREch1IOoKpIl5UokSv+AxBVIjR7ybkXHQqFYjxK5ApFjqNErlDkOErkiv8dufyK7k6QFrmnW0BOIEsaoYFMaKHyaomcOcLGTamaeJBauTQGqWs57wGGbkSVK0l4yhaCZ8nc+HgcYzEEX06WWJkGRICAw8Nc1/2FhfcKITLeiBHRiveTUC/rAQCAaOhGLxAxALinoKCns5UxzeM6JyDGtJ4/WkzTb5qmuzqXv15cUnq1m3gKR6eXehMi0P10tQsA7jYM32SmCebn69xOXI+qyFRW2LZi14LBPAYAD8+dF7/cPjw4gEzztCsJoflYR+OZykgkGAw6jsNcjP2IAGDlqiW/NIrEAHp5Ri8RIEIqhU1NomrxUpGpwh8ics4LCwsjkfK2H78x/P6Mh3kEIqEZRuxKJ8Rjj85fwIQQy1evDpHV9sPXZv5d3EkBkQc34aR8gWC0sz3W2rR23ZNy8YCbhkIEgGXLFscHK376ORkKMYe7fpHc2TgH08RLHdBwNlBdvWqyQF0Ioev6ihUrOxpOWwP9TNeIe/OSCeE4Zih44bsTJbMCjyxYiJZl+f3+uqMf1B48vPVI/azS+5KDg54rokZCM/w6Y8drNlfkOR99+hnI9QOu6pxz7vP53jt05FhdzcmvCkrDPJHItQrHt0bWnzFNAPBterYvL3/Th3XvEgEiZpQ6Edm2Xb3mCa1y6bqaN62EJYTX2rsTAJmhUHfL+eM7nj76/qHH1qzBVCoFAIJo58svnT776/IXdxeVz82StNPMQERM04b6ehs+Psgvn/+y/lQ4HOaca26HyNIKjmPv2L7zt3PHdu8KVJQz8lRFHALGINoLb7+T+Kur6vMvPikuCQshJhtGydviuebmZzZuKFmydtFT22T9cw/l4QgA6c/mxjOH9z23cf2+2v2O4yDn6UwyARyofeNk/Sny5xGRd3JwBMA0RsnhqnmVe/a/VVxc5PJofAxCCI0xQXzvngPff3siEBiEEfF7A2SMEgljYdXjr+19paio5F9NQ0SaprW0tr6+69Xfr3Qxw09Tb+CYAyAAgMmTW7Zu2bzteSZjHs45AMghKGMsGo22tVx0+URnGATBRdmcOfc/8CAAZI/CJaOm6e6+1t5+yUsKB0R0HKesLByJTMM0cnAOAC0XL/T29DCNeeiJRcQYm1+1KBgMCiHSdSmkyOXXnHPDMNw9SxeRIxfXo/SJkBBcCC+bxrZtRJy6aWQ9X1337iJL27Y1TZOZi78BhlErvMRqRCAAAAAASUVORK5CYII=)"]},{"cell_type":"markdown","metadata":{"id":"FeF_omkZFjwc"},"source":["*The friend-of-a-friend recommendation algorithm in action. Mary has two friends: Fred and Bob. One of these friends (Bob) is randomly selected. Bob has two additional friends: Marty and Alice. Neither Alice nor Marty are friends with Mary. A friend of a friend (Marty) is randomly selected. Mary receives an email suggesting that she should send a friend request to Marty.*"]},{"cell_type":"markdown","metadata":{"id":"4l0MExh7Fmxx"},"source":["Essentially, the algorithm assumes that a friend of your friend is also likely to be your friend. This assumption is reasonable but also a bit simplistic. How well does this assumption hold? Nobody knows! However, as the company’s first data scientist, it’s your job to find out. You have been tasked with building a model that predicts student behavior in response to the recommendation algorithm.\n","\n","Your task is to build a model that predicts user behavior based on user profiles and social network data. The model must generalize to other colleges and universities. This generalizability is very important—a model that cannot be utilized at other colleges is worthless to the product team. Consider, for example, a model that accurately predicts behavior in one or two of the dorms at the sampled university. In other words, it requires specific dorm names to make accurate predictions. Such a model is not useful because other universities will have different dormitory names. Ideally, the model should generalize to all dormitories across all universities worldwide.\n","\n","Once you’ve built the generalized model, you should explore its inner workings. Your goal is to gain insights into how university life facilitates new FriendHook connections.\n","\n","The project goals are ambitious but also very doable. You can complete them by carrying out the following tasks:\n","\n","1. Load the three datasets pertaining to user behavior, user profiles, and the user friendship network. Explore each dataset, and clean it as required.\n","2. Build and evaluate a model that predicts user behavior based on user profiles and established friendship connections. You can optionally split this task into two subtasks: build a model using just the friendship network, and then add the profile information and test whether this improves the model’s performance.\n","3. Determine whether the model generalizes well to other universities.\n","4. Explore the inner workings of the model to gain better insights into student behavior.\n","\n","Our data contains three files stored in a friendhook directory. These files are CSV tables and are named Profiles.csv, Observations.csv, and Friendships.csv. Let’s discuss each table individually.\n","\n","**The Profiles table**\n","\n","Profiles.csv contains profile information for all the students at the chosen university. This information is distributed across six columns: `Profile_ID`, `Sex`, `Relationship_ Status`, `Major`, `Dorm`, and `Year`. Maintaining student privacy is very important to the FriendHook team, so all the profile information has been carefully encrypted. FriendHook’s encryption algorithm takes in descriptive text and returns a unique, scrambled 12-character code known as a *hash code*. Suppose, for example, that a student lists their major as physics. The word *physics* is then scrambled and replaced with a hash code such as *b90a1221d2bc*. If another student lists their major as art history, a different hash code is returned (for example, *983a9b1dc2ef*). In this manner, we can check whether two students share the same major without necessarily knowing the identity of that major. All six profile columns have been encrypted as a precautionary measure. Let’s discuss the separate columns in detail:\n","\n","- `Profile_ID`—A unique identifier used to track each student. The identifier can be linked to the user behaviors in the `Observations` table. It can also be linked to FriendHook connections in the `Friendships` table.\n","- `Sex`—This optional field describes the sex of a student as `Male` or `Female`. Students who don’t wish to specify a gender can leave the `Sex` field blank. Blank inputs are stored as empty values in the table.\n","- `Relationship_Status`—This optional field specifies the relationship status of the student. Each student has three relationship categories to choose from: `Single`, `In a Relationship`, or `It’s Complicated`. All students have a fourth option of leaving this field blank. Blank inputs are stored as empty values in the table.\n","- `Major`—The chosen area of study for the student, such as physics, history, economics, etc. This field is required to activate a FriendHook account. Students who have not yet picked their major can select `Undecided` from among the options.\n","- `Dorm`—The name of the dormitory where the student resides. This field is required to activate a FriendHook account. Students who reside in off-campus housing can select `Off-Campus Housing` from among the options.\n","- `Year`—The undergraduate student’s year. This field must be set to one of four options: `Freshman`, `Sophomore`, `Junior`, or `Senior`.\n","\n","**The Observations table**\n","\n","Observations.csv contains the observed user behavior in response to the emailed friend recommendation. It includes the following five fields:\n","\n","- `Profile_ID`—The ID of the user who received a friend recommendation. The ID corresponds to the profile ID in the `Profiles` table.\n","- `Selected_Friend`—An existing friend of the user in the `Profile_ID` column.\n","- `Selected_Friend_of_Friend`—A randomly chosen friend of `Selected_Friend` who is not yet a friend of `Profile_ID`. This random friend of a friend is emailed as a friend recommendation for the user.\n","- `Friend_Requent_Sent`—A Boolean column that is `True` if a user sends a friend request to the suggested friend of a friend or `False` otherwise.\n","- `Friend_Request_Accepted`—A Boolean column that is `True` only if a user sends a friend request and that request is accepted.\n","\n","This table stores all the observed user behaviors in response to the weekly recommendation email. Our goal is to predict the Boolean outputs of the final two table columns based on the profile and social networking data.\n","\n","**The Friendships table**\n","\n","Friendships.csv contains the FriendHook friendship network corresponding to the selected university. This network was used as input into the friend-of-a-friend recommendation algorithm. The `Friendships` table has just two columns: `Friend A` and `Friend B`. These columns contain profile IDs that map to the `Profile_ID` columns of the `Profiles` and `Observations` tables. Each row corresponds to a pair of FriendHook friends. For instance, the first row contains IDs `b8bc075e54b9` and `49194b3720b6`. From these IDs, we can infer that the associated students have an established FriendHook connection. Using the IDs, we can look up the profile of each student. The profiles then allow us to explore whether the friends share the same major or reside together in the same dorm.\n","\n","To address the problem at hand, we need to know how to do the following:\n","\n","- Analyze network data using Python\n","- Discover friendship clusters in social networks\n","- Train and evaluate supervised machine learning models\n","- Probe the inner workings of trained models to draw insights from our data\n","\n","FriendHook is a popular social networking app designed for college campuses. Students can connect as friends in the FriendHook network. A recommendation engine emails users weekly with new friend suggestions based on their existing connections; students can ignore these recommendations, or they can send out friend requests. We have been provided with one week’s worth of data pertaining to friend recommendations and student responses. That data is stored in the friendhook/Observations.csv file. We’re provided with two additional files: friendhook/Profiles.csv and friendhook/Friendships.csv, containing user profile information and the friendship graph, respectively. The user profiles have been encrypted to protect student privacy. Our goal is to build a model that predicts user behavior in response to the friend recommendations. We will do so by following these steps:\n","\n","1. Load the three datasets containing the observations, user profiles, and friendship connections.\n","2. Train and evaluate a supervised model that predicts behavior based on network features and profile features. We can optionally split this task into two subtasks: training a model using network features, and then adding profile features and evaluating the shift in model performance.\n","3. Check to ensure that the model generalizes well to other universities.\n","4. Explore the inner workings of our model to gain better insights into student behavior."]},{"cell_type":"code","metadata":{"id":"5Qv4ngnqR5sf"},"source":["import warnings\n","warnings.filterwarnings('ignore')"],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"Z9S5jC3VSibR","executionInfo":{"status":"ok","timestamp":1637511500127,"user_tz":-330,"elapsed":1688,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"f3473e09-508e-465f-852a-3e649822333a"},"source":["!wget -q --show-progress https://github.com/sparsh-ai/general-recsys/raw/T426474/Case_Study5/friendhook/Friendships.csv\n","!wget -q --show-progress https://github.com/sparsh-ai/general-recsys/raw/T426474/Case_Study5/friendhook/Observations.csv\n","!wget -q --show-progress https://github.com/sparsh-ai/general-recsys/raw/T426474/Case_Study5/friendhook/Profiles.csv"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Friendships.csv 100%[===================>] 2.19M --.-KB/s in 0.02s \n","Observations.csv 100%[===================>] 196.39K --.-KB/s in 0.004s \n","Profiles.csv 100%[===================>] 302.93K --.-KB/s in 0.004s \n"]}]},{"cell_type":"markdown","metadata":{"id":"Rq1BGCEHR5sn"},"source":["## Exploring the Data\n","\n","Let's separately explore the _Profiles_, _Observations_ and _Friendships_ tables.\n","\n","### Examining the Profiles\n","We'll start by loading the _Profiles_ table into Pandas and summarizing the table's contents.\n","\n","**Loading the Profiles table**"]},{"cell_type":"code","metadata":{"id":"lGpfo2Q1R5sq","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511510773,"user_tz":-330,"elapsed":452,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"38efdd5e-26b5-4a32-d84e-27ded04a8d66"},"source":["import pandas as pd\n","\n","def summarize_table(df):\n"," n_rows, n_columns = df.shape\n"," summary = df.describe()\n"," print(f\"The table contains {n_rows} rows and {n_columns} columns.\")\n"," print(\"Table Summary:\\n\")\n"," print(summary.to_string())\n","\n","df_profile = pd.read_csv('Profiles.csv')\n","summarize_table(df_profile)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The table contains 4039 rows and 6 columns.\n","Table Summary:\n","\n"," Profile_ID Sex Relationship_Status Dorm Major Year\n","count 4039 4039 3631 4039 4039 4039\n","unique 4039 2 3 15 30 4\n","top 03b574e6cef3 e807eb960650 ac0b88e46e20 a8e6e404d1b3 141d4cdd5aaf c1a648750a4b\n","freq 1 2020 1963 2739 1366 1796\n"]}]},{"cell_type":"markdown","metadata":{"id":"UGwQZxlNR5ss"},"source":["There is one place in the table summary where the numbers are off; the _Relationship Status_ column. Pandas has detected three _Relationship Status_ categories across 3631 of 4039 table rows. The remaining 400 or so rows are null. They don't contain any assigned relationship status. Lets count the total number of empty rows.\n","\n","**Counting empty Relationship Status profiles**"]},{"cell_type":"code","metadata":{"id":"p9k-ODzhR5st","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511517033,"user_tz":-330,"elapsed":421,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"e120f3f6-2bc2-493b-c500-aa47f8c924ae"},"source":["is_null = df_profile.Relationship_Status.isnull()\n","num_null = df_profile[is_null].shape[0]\n","print(f\"{num_null} profiles are missing the Relationship Status field.\")"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["408 profiles are missing the Relationship Status field.\n"]}]},{"cell_type":"markdown","metadata":{"id":"hZyWW76fR5su"},"source":["408 profiles do not contain a listed relationship status. We can treat the lack of status as a fourth _unspecified_ relationship status category. Hence, we should assign these rows a category id. What id value should we choose? Before we answer the question, lets examine all unique ids within the _Relationship Status_ column.\n","\n","**Checking unique Relationship Status values**"]},{"cell_type":"code","metadata":{"id":"Sdlzm8CRR5sv","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511519520,"user_tz":-330,"elapsed":7,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"c6bc7dcf-5cab-4beb-f2cc-b26bed9b70c1"},"source":["unique_ids = set(df_profile.Relationship_Status.values)\n","print(unique_ids)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["{nan, '188f9a32c360', 'ac0b88e46e20', '9cea719429e9'}\n"]}]},{"cell_type":"markdown","metadata":{"id":"zS5YSLPwR5sx"},"source":["The Scikit-Learn library is unable to process hash-codes or null values. It can only process numbers. Hence, we'll need to eventually convert the categories to numeric values. \n","\n","**Mapping Relationship Status values to numbers**"]},{"cell_type":"code","metadata":{"id":"5a7Y6WJvR5sy"},"source":["import numpy as np\n","category_map = {'9cea719429e9': 0, np.nan: 1, '188f9a32c360': 2, \n"," 'ac0b88e46e20': 3}"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"iluKRgqkR5s0"},"source":["Next, we'll replace the contents of the _Relationship Status_ column with the appropriate numeric values.\n","\n","**Updating the Relationship Status column**"]},{"cell_type":"code","metadata":{"id":"9x0FZu3zR5s0","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511558269,"user_tz":-330,"elapsed":10,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"2bd5bd0a-de9b-4f18-a912-c4f37bf4a326"},"source":["nums = [category_map[hash_code] \n"," for hash_code in df_profile.Relationship_Status.values]\n","df_profile['Relationship_Status'] = nums\n","print(df_profile.Relationship_Status)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["0 0\n","1 3\n","2 3\n","3 3\n","4 0\n"," ..\n","4034 3\n","4035 0\n","4036 3\n","4037 3\n","4038 0\n","Name: Relationship_Status, Length: 4039, dtype: int64\n"]}]},{"cell_type":"markdown","metadata":{"id":"zStc1B59R5s1"},"source":["We've transformed _Relationship Status_ into a numeric variable. However, the remaining five columns in the table still contain hash-codes. Let's create a category mapping between hash-codes and numbers in each column. We'll track the category mappings in each column with a `col_to_mapping` dictionary. We'll also leverage the mappings in order to replace all hash-codes with numbers in `df_profile`.\n","\n","**Replacing all Profile hash-codes with numeric values**"]},{"cell_type":"code","metadata":{"id":"yDm83aBZR5s1","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511561919,"user_tz":-330,"elapsed":433,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"110fa181-5c97-4182-bdef-6dadf77ce0dd"},"source":["col_to_mapping = {'Relationship_Status': category_map}\n","\n","for column in df_profile.columns:\n"," if column in col_to_mapping:\n"," continue\n"," \n"," unique_ids = sorted(set(df_profile[column].values))\n"," category_map = {id_: i for i, id_ in enumerate(unique_ids)}\n"," col_to_mapping[column] = category_map\n"," nums = [category_map[hash_code] \n"," for hash_code in df_profile[column].values]\n"," df_profile[column] = nums\n","\n","head = df_profile.head()\n","print(head.to_string(index=False))"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":[" Profile_ID Sex Relationship_Status Dorm Major Year\n"," 2899 0 0 5 13 2\n"," 1125 0 3 12 6 1\n"," 3799 0 3 12 29 2\n"," 3338 0 3 4 25 0\n"," 2007 1 0 12 2 0\n"]}]},{"cell_type":"markdown","metadata":{"id":"s-ToK8jUR5s3"},"source":["We've finished tweaking the `df_profile`. Now lets turn our attention to the table of experimental observations.\n","\n","### Exploring the Experimental Observations\n","We'll start by loading the _Observations_ table into Pandas and summarizing the table's contents.\n","\n","**Loading the Observations table**"]},{"cell_type":"code","metadata":{"id":"IKHOylu-R5s3","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511580047,"user_tz":-330,"elapsed":425,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"3205f7cc-6adb-483e-be43-1759cf47d799"},"source":["df_obs = pd.read_csv('Observations.csv')\n","summarize_table(df_obs)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The table contains 4039 rows and 5 columns.\n","Table Summary:\n","\n"," Profile_ID Selected_Friend Selected_Friend_of_Friend Friend_Request_Sent Friend_Request_Accepted\n","count 4039 4039 4039 4039 4039\n","unique 4039 2219 2327 2 2\n","top 43928bbe27fd 89581f99fa1e 6caa597f13cc True True\n","freq 1 77 27 2519 2460\n"]}]},{"cell_type":"markdown","metadata":{"id":"SL0z-jZyR5s4"},"source":["The five table columns all consistantly show 4039 filled rows. There are no empty values in the table. This is good. However, the actual column names are hard to read. The names are very descriptive, but also very long. We should shorten some of the names in order to ease our cognitive load. \n","\n","**Renaming the observation columns**"]},{"cell_type":"code","metadata":{"id":"0QykAd_YR5s5","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511582221,"user_tz":-330,"elapsed":9,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"53fe4b1b-f161-4284-d5a5-57517a8430f2"},"source":["new_names = {'Selected_Friend': 'Friend', \n"," 'Selected_Friend_of_Friend': 'FoF',\n"," 'Friend_Request_Sent': 'Sent',\n"," 'Friend_Request_Accepted': 'Accepted'}\n","df_obs = df_obs.rename(columns=new_names)\n","summarize_table(df_obs)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The table contains 4039 rows and 5 columns.\n","Table Summary:\n","\n"," Profile_ID Friend FoF Sent Accepted\n","count 4039 4039 4039 4039 4039\n","unique 4039 2219 2327 2 2\n","top 43928bbe27fd 89581f99fa1e 6caa597f13cc True True\n","freq 1 77 27 2519 2460\n"]}]},{"cell_type":"markdown","metadata":{"id":"Ou5Xqi_aR5s5"},"source":["Approximately 62% (2519) of the friend suggestions lead to friend request being sent. This is very promising; the friend-of-a-friend suggestions are quite effective. Furthermore, approximately 60% (2460) of sampled instances led to a friend request getting accepted. Hence, the sent friend requests are ignored or rejected just 2% (2519 - 2460 = 50) of the time. Of course, our numbers assume that there are no observations where _Sent_ is False and _Accepted_ is True. This scenario is not possible, because a friend-request cannot be accepted if it has not yet been sent. Still, as sanity check, lets test the integrity of the data by confirm that the scenario does not take place.\n","\n","**Ensuring that Sent is `True` for all accepted requests**"]},{"cell_type":"code","metadata":{"id":"6lbK8y0-R5s6"},"source":["condition = (df_obs.Sent == False) & (df_obs.Accepted == True)\n","assert not df_obs[condition].shape[0]"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"p8brARl6R5s6"},"source":["Based on our observations, user behavior follows three possible scenarios. Hence, we can encode this categorical behavior by assigning numbers `0`, `1`, and `2` to the behavior patterns.\n","\n","**Assigning classes of behavior to the user observations**"]},{"cell_type":"code","metadata":{"id":"Rm1IbPpDR5s7"},"source":["behaviors = []\n","for sent, accepted in df_obs[['Sent', 'Accepted']].values:\n"," behavior = 2 if (sent and not accepted) else int(sent) * int(accepted)\n"," behaviors.append(behavior)\n","df_obs['Behavior'] = behaviors"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"uEqNg7SqR5s7"},"source":["Additionally, we must transform the profile ids in the first three columns from hash-codes to numeric ids that are consistent with `df_profile.Profile_ID`. \n","\n","**Replacing all Observation hash-codes with numeric values**"]},{"cell_type":"code","metadata":{"id":"nnVtphvHR5s7","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511585199,"user_tz":-330,"elapsed":6,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"0c9abbe6-fe38-421c-839a-7ecced2909b4"},"source":["for col in ['Profile_ID', 'Friend', 'FoF']:\n"," nums = [col_to_mapping['Profile_ID'][hash_code]\n"," for hash_code in df_obs[col]]\n"," df_obs[col] = nums\n","\n","head = df_obs.head()\n","print(head.to_string(index=False))"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":[" Profile_ID Friend FoF Sent Accepted Behavior\n"," 2485 2899 2847 False False 0\n"," 2690 2899 3528 False False 0\n"," 3904 2899 3528 False False 0\n"," 709 2899 3403 False False 0\n"," 502 2899 345 True True 1\n"]}]},{"cell_type":"markdown","metadata":{"id":"RKYhXx1qR5s8"},"source":["The `df_obs` now aligns with `df_profile`. Only a single data table remains unanalyzed. Lets proceed to explore the friendship linkages within the remaining _Friendships_ table.\n","\n","\n","### Exploring Friendships Linkage Table\n","We'll start by loading the _Friendships_ table into Pandas and summarizing the table's contents.\n","\n","**Loading the Friendships table**"]},{"cell_type":"code","metadata":{"id":"6rfPDqBNR5s8","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511594631,"user_tz":-330,"elapsed":581,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"680d7d2b-c617-457e-8368-5eed9a2709ae"},"source":["df_friends = pd.read_csv('Friendships.csv')\n","summarize_table(df_friends)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The table contains 88234 rows and 2 columns.\n","Table Summary:\n","\n"," Friend_A Friend_B\n","count 88234 88234\n","unique 3646 4037\n","top 89581f99fa1e 97ba93d9b169\n","freq 1043 251\n"]}]},{"cell_type":"markdown","metadata":{"id":"CQZ8eJ5wR5s9"},"source":["In order to carry out a more detailed analysis, we should load the frienship data into a NetworkX graph. \n","\n","**Loading the social graph into NetworkX**"]},{"cell_type":"code","metadata":{"id":"mGF4ZMpsR5s9","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511595734,"user_tz":-330,"elapsed":620,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"8a4b0ce4-457c-44cf-b442-8660b405842c"},"source":["import networkx as nx\n","G = nx.Graph()\n","for id1, id2 in df_friends.values:\n"," node1 = col_to_mapping['Profile_ID'][id1]\n"," node2 = col_to_mapping['Profile_ID'][id2]\n"," G.add_edge(node1, node2)\n"," \n","nodes = list(G.nodes)\n","num_nodes = len(nodes)\n","print(f\"The social graph contains {num_nodes} nodes.\")"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The social graph contains 4039 nodes.\n"]}]},{"cell_type":"markdown","metadata":{"id":"0kLVaYBsR5s9"},"source":["Lets try to gain more insights into the graph structure by visualizing it with `nx.draw`. Please note the graph is rather large, so visulization might take 10-30 seconds to load.\n","\n","**Visualizing the social graph**"]},{"cell_type":"code","metadata":{"id":"xmk3JhjQR5s9","colab":{"base_uri":"https://localhost:8080/","height":319},"executionInfo":{"status":"ok","timestamp":1637511667288,"user_tz":-330,"elapsed":69058,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"b0f7ab28-f207-4190-bc50-02a56d76bda5"},"source":["import matplotlib.pyplot as plt\n","import numpy as np\n","np.random.seed(0)\n","nx.draw(G, node_size=5)\n","plt.show()"],"execution_count":null,"outputs":[{"output_type":"display_data","data":{"image/png":"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\n","text/plain":["
"]},"metadata":{}}]},{"cell_type":"markdown","metadata":{"id":"DA4vLks5R5s-"},"source":["Tightly clustered social groups are clearly visible within the network. Lets extract these groups using Markov clustering. \n","\n","**Finding social groups using Markov clustering**"]},{"cell_type":"code","metadata":{"id":"szZqOhZZTLzI"},"source":["!pip install -q markov_clustering"],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"j2lf-aypR5s-","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511675632,"user_tz":-330,"elapsed":2648,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"47952b39-0748-45b1-d21a-d6a2e80d9cd3"},"source":["import markov_clustering as mc\n","matrix = nx.to_scipy_sparse_matrix(G)\n","result = mc.run_mcl(matrix)\n","clusters = mc.get_clusters(result) \n","num_clusters = len(clusters)\n","print(f\"{num_clusters} clusters were found in the social graph.\")"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["10 clusters were found in the social graph.\n"]}]},{"cell_type":"markdown","metadata":{"id":"Aaz8KRiLR5s-"},"source":["Ten clusters were found in the social graph. Lets visualize these clusters by coloring each node based on cluster id. To start, we'll need to iterate over `clusters` and assign a `cluster_id` attribute to every node.\n","\n","**Assigning cluster attributes to nodes**"]},{"cell_type":"code","metadata":{"id":"jKBZmK0CR5s-"},"source":["for cluster_id, node_indices in enumerate(clusters):\n"," for i in node_indices:\n"," node = nodes[i]\n"," G.nodes[node]['cluster_id'] = cluster_id"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"aSXRgvFAR5s_"},"source":["Next, we'll color the nodes based on their attribute assignment.\n","\n","**Coloring the nodes by cluster assignment**"]},{"cell_type":"code","metadata":{"id":"5ahEfgRFR5s_","colab":{"base_uri":"https://localhost:8080/","height":319},"executionInfo":{"status":"ok","timestamp":1637511748316,"user_tz":-330,"elapsed":69108,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"6a083d3c-198b-4b25-910a-00c8e6fe660d"},"source":["np.random.seed(0)\n","colors = [G.nodes[n]['cluster_id'] for n in G.nodes]\n","nx.draw(G, node_size=5, node_color=colors, cmap=plt.cm.tab20)\n","plt.show()"],"execution_count":null,"outputs":[{"output_type":"display_data","data":{"image/png":"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\n","text/plain":["
"]},"metadata":{}}]},{"cell_type":"markdown","metadata":{"id":"ezbAq8OSR5tA"},"source":["The cluster colors clearly correspond to tight social groups. Our clustering thus has been effective. Hence, the assigned `cluster_id` attributes should prove useful during the model-building process. In this same manner, it might be useful to store all five profile features as attributes within the student nodes. \n","\n","**Assigning profile attributes to nodes**"]},{"cell_type":"code","metadata":{"id":"s5x-wrTzR5tA","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511749092,"user_tz":-330,"elapsed":783,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"dcdfe7f4-7a28-4626-97e0-949bca1ba0f2"},"source":["attribute_names = df_profile.columns\n","for attributes in df_profile.values:\n"," profile_id = attributes[0]\n"," for name, att in zip(attribute_names[1:], attributes[1:]):\n"," G.nodes[profile_id][name] = att\n"," \n","first_node = nodes[0]\n","print(f\"Attributes of node {first_node}:\")\n","print(G.nodes[first_node])"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Attributes of node 2899:\n","{'cluster_id': 0, 'Sex': 0, 'Relationship_Status': 0, 'Dorm': 5, 'Major': 13, 'Year': 2}\n"]}]},{"cell_type":"markdown","metadata":{"id":"hz2gpSS8R5tB"},"source":["We have finished exploring our input data. Now, we'll proceed to train a model that predicts user behavior. We'll start by constructing simple model that only utilizes network features.\n","\n","## Training a Predictive Model Using Network Features\n","\n","Our goal is to train a supervised ML model on our dataset, in order to predict user behavior. Currently, all possible classes of behavior are stored within the _Behavior_ columns of `df_obs`. We'll assign our training class-label array to equal the `df_obs.Behavior` column.\n","\n","**Assigning the class-label array `y`**"]},{"cell_type":"code","metadata":{"id":"RpMLjsHwR5tB","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511749093,"user_tz":-330,"elapsed":44,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"c7b9d27d-30a4-496b-b193-76f2d70b6ea8"},"source":["y = df_obs.Behavior.values\n","print(y)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[0 0 0 ... 1 1 1]\n"]}]},{"cell_type":"markdown","metadata":{"id":"A1uWDrQHR5tC"},"source":["Now that we have class-labels, we'll need to create a feature-matrix `X`. Let's create an initial version of `X`, and populate it with some very basic features. The simplest question we can ask about a person within a social network is this; how many friends does the person have? Of course, that value equals edge-count associated with the person's node within the social graph. Lets make the edge-count our first feature in the feature-matrix. We'll iterate over all the rows in `df_obs` and assign an edge-count to each profile that's referenced within each row. \n","\n","**Creating a feature-matrix from edge counts**"]},{"cell_type":"code","metadata":{"id":"S5mqLCFyR5tD"},"source":["cols = ['Profile_ID', 'Friend', 'FoF']\n","features = {f'{col}_Edge_Count': [] for col in cols}\n","for node_ids in df_obs[cols].values:\n"," for node, feature_name in zip(node_ids, features.keys()):\n"," degree = G.degree(node)\n"," features[feature_name].append(degree)\n","\n","df_features = pd.DataFrame(features)\n","X = df_features.values"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"g29SJDPtR5tD"},"source":["Lets quickly check the quality of the signal in the training data by training and testing a simple model. We have multiple possible models to choose from. One sensible choice is a decision tree classifier. Decision trees can handle non-linear decision boundaries and are easily interpretable. \n","\n","**Training and evaluating a Decision tree classifier**"]},{"cell_type":"code","metadata":{"id":"u8g5qI7qR5tD","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511922904,"user_tz":-330,"elapsed":4,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"2d41bdd3-2e1e-4d54-904a-531788a64ed9"},"source":["np.random.seed(0)\n","from sklearn.tree import DecisionTreeClassifier\n","from sklearn.model_selection import train_test_split\n","from sklearn.metrics import f1_score\n","\n","def evaluate(X, y, model_type=DecisionTreeClassifier, **kwargs):\n"," np.random.seed(0)\n"," X_train, X_test, y_train, y_test = train_test_split(X, y)\n"," clf = model_type(**kwargs)\n"," clf.fit(X_train, y_train)\n"," pred = clf.predict(X_test)\n"," f_measure = f1_score(pred, y_test, average='macro')\n"," return f_measure, clf\n","\n","f_measure, clf = evaluate(X, y)\n","print(f\"The f-measure is {f_measure:0.2f}\")"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The f-measure is 0.37\n"]}]},{"cell_type":"markdown","metadata":{"id":"U8UWaIfIR5tE"},"source":["Our f-measure is terrible! Clearly, friend-count by itself is not a sufficient signal for predicting user-behavior. Perhaps adding PageRank values to our training set will yield improved results? \n","\n","**Adding PageRank features**"]},{"cell_type":"code","metadata":{"id":"LueVuNuUR5tE","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511925750,"user_tz":-330,"elapsed":1074,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"0bb4aa49-a632-4b5d-f096-43e8219bfd0d"},"source":["np.random.seed(0)\n","node_to_pagerank = nx.pagerank(G)\n","features = {f'{col}_PageRank': [] for col in cols}\n","for node_ids in df_obs[cols].values:\n"," for node, feature_name in zip(node_ids, features.keys()):\n"," pagerank = node_to_pagerank[node]\n"," features[feature_name].append(pagerank)\n","\n","def update_features(new_features):\n"," for feature_name, values in new_features.items():\n"," df_features[feature_name] = values\n"," return df_features.values\n","\n","X = update_features(features)\n","f_measure, clf = evaluate(X, y)\n","\n","print(f\"The f-measure is {f_measure:0.2f}\")"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The f-measure is 0.38\n"]}]},{"cell_type":"markdown","metadata":{"id":"miyHKkVmR5tF"},"source":["The f-measure remains approximately the same. Basic centrality measures are insufficient. We need to expand `X` to include the social groups uncovered by Markov Clustering. One approach is just consider the following binary question; are two people in the same social group? Yes or no? If they are, then perhaps they are more likely to eventually become friends on FriendHook. We can make this binary comparison between each pair of profile-ids within a single row of observations. \n","\n","**Adding social group features**"]},{"cell_type":"code","metadata":{"id":"Z5sHBEI7R5tF","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511926180,"user_tz":-330,"elapsed":6,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"ac73b828-4108-4aac-c1c4-2ab6dc25591b"},"source":["np.random.seed(0)\n","features = {f'Shared_Cluster_{e}': []\n"," for e in ['id_f', 'id_fof', 'f_fof']}\n","\n","i = 0\n","for node_ids in df_obs[cols].values:\n"," c_id, c_f, c_fof = [G.nodes[n]['cluster_id'] \n"," for n in node_ids]\n"," features['Shared_Cluster_id_f'].append(int(c_id == c_f))\n"," features['Shared_Cluster_id_fof'].append(int(c_id == c_fof))\n"," features['Shared_Cluster_f_fof'].append(int(c_f == c_fof))\n"," \n","X = update_features(features)\n","f_measure, clf = evaluate(X, y)\n","print(f\"The f-measure is {f_measure:0.2f}\") "],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The f-measure is 0.43\n"]}]},{"cell_type":"markdown","metadata":{"id":"Fbp2DmCJR5tG"},"source":["Our f-measure has noticeably improved, from 0.38 to 0.43. Perfomance is still poor. Nonetheless, the social group inclusion has led a slight enhacement of our model. How important are the new social group features relative the model's current perfomance? We can find check, using the `feature_importance_` attribute of our trained classifier.\n","\n","**Ranking features by their importance score**"]},{"cell_type":"code","metadata":{"id":"8HzVCA25R5tG","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511927730,"user_tz":-330,"elapsed":8,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"ac0094ae-c96c-47e3-ddd5-b9be90dbbd5b"},"source":["def view_top_features(clf, feature_names):\n"," for i in np.argsort(clf.feature_importances_)[::-1]:\n"," feature_name = feature_names[i]\n"," importance = clf.feature_importances_[i]\n"," if not round(importance, 2):\n"," break\n"," \n"," print(f\"{feature_name}: {importance:0.2f}\")\n","feature_names = df_features.columns\n","view_top_features(clf, feature_names)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Shared_Cluster_id_fof: 0.18\n","FoF_PageRank: 0.17\n","Profile_ID_PageRank: 0.17\n","Friend_PageRank: 0.15\n","FoF_Edge_Count: 0.12\n","Profile_ID_Edge_Count: 0.11\n","Friend_Edge_Count: 0.10\n"]}]},{"cell_type":"markdown","metadata":{"id":"Tketm2ZTR5tH"},"source":["Social graph centrality plays some role in friendship determination. Of course, our model's performance is still poor, so we should be cautious with our inferences on how the features drive predictions. What other graph-based features could we utilize? Perhaps the network cluster size can impact the predictions? We can find out. However, we should be cautious in our efforts to keep our model generalizable. Cluster size can inexplicably take the place of cluster-id, making the model very specific to the university. \n","\n","**Adding cluster-size features**"]},{"cell_type":"code","metadata":{"id":"23WZ_Zr5R5tH","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511937961,"user_tz":-330,"elapsed":447,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"214acf3c-2834-4061-bf72-4673500cbd8c"},"source":["np.random.seed(0)\n","cluster_sizes = [len(cluster) for cluster in clusters]\n","features = {f'{col}_Cluster_Size': [] for col in cols}\n","for node_ids in df_obs[cols].values:\n"," for node, feature_name in zip(node_ids, features.keys()):\n"," c_id = G.nodes[node]['cluster_id']\n"," features[feature_name].append(cluster_sizes[c_id])\n"," \n","X = update_features(features)\n","f_measure, clf = evaluate(X, y)\n","print(f\"The f-measure is {f_measure:0.2f}\")"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The f-measure is 0.43\n"]}]},{"cell_type":"markdown","metadata":{"id":"_8adpXgZR5tH"},"source":["The cluster did not improve the model. As a precaution, lets delete it from our feature set.\n","\n","**Deleting cluster-size features**"]},{"cell_type":"code","metadata":{"id":"iKZyxJjIR5tI"},"source":["import re\n","def delete_features(df_features, regex=r'Cluster_Size'):\n"," \n"," df_features.drop(columns=[name for name in df_features.columns\n"," if re.search(regex, name)], inplace=True)\n"," return df_features.values\n","\n","X = delete_features(df_features)"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"SuB6EnwoR5tI"},"source":["The f-measure remains at 0.43. Perhaps we should try thinking outside the box. In what ways can social connections drive real world-behavior? Consider the following scenario. Suppose we analyze a student named Alex, whose node id in network `G` is `n`. Alex has 50 FriendHook friends. These are accessible through `G[n]`. We randomly sample two of the friends in `G[n]`. Their node ids are `a` and `b`. We then check if `a` and `b` are friends. They are! It seems that `a` is in `list(G[n])`. We then repeat this 100 times. In 95% percent of sampled instances, `a` is friend of `b`. Basically, there's a 95% likelihood that any pair of Alex's friends are also friends with each other. We'll refer to this probability as the **friend-sharing likelihood**. Lets try incorporating this likelihood into our features. We'll start by computing the likehood for every node in `G`. \n","\n","**Computing friend-sharing likelihoods**"]},{"cell_type":"code","metadata":{"id":"6sddUPr3R5tI"},"source":["friend_sharing_likelihood = {}\n","for node in nodes:\n"," neighbors = list(G[node])\n"," friendship_count = 0\n"," total_possible = 0\n"," for i, node1 in enumerate(neighbors[:-1]):\n"," for node2 in neighbors[i + 1:]:\n"," if node1 in G[node2]:\n"," friendship_count += 1\n"," \n"," total_possible += 1\n"," \n"," prob = friendship_count / total_possible if total_possible else 0\n"," friend_sharing_likelihood[node] = prob"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"_pf4DSThR5tJ"},"source":["Next, we'll generate a friend-sharing likelihood feature for each of our three profile ids. After adding the features, we'll re-valuate the trained model's performance.\n","\n","**Adding friend-sharing likelihood features**"]},{"cell_type":"code","metadata":{"id":"E0CaSuAkR5tJ","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511959812,"user_tz":-330,"elapsed":31,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"e96b9192-271f-4fb2-a0bf-4305bfcaffd1"},"source":["np.random.seed(0)\n","features = {f'{col}_Friend_Sharing_Likelihood': [] for col in cols}\n","for node_ids in df_obs[cols].values:\n"," for node, feature_name in zip(node_ids, features.keys()):\n"," sharing_likelihood = friend_sharing_likelihood[node]\n"," features[feature_name].append(sharing_likelihood)\n","\n","X = update_features(features)\n","f_measure, clf = evaluate(X, y)\n","print(f\"The f-measure is {f_measure:0.2f}\")"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The f-measure is 0.49\n"]}]},{"cell_type":"markdown","metadata":{"id":"lzSCCbP-R5tK"},"source":["Performance has increased from 0.43 to 0.49! It's still not great, but its progressively getting better. How does the friend-sharing likelihood compare to other features in the model? Lets find out!\n","\n","**Ranking features by their importance score**"]},{"cell_type":"code","metadata":{"id":"xQ0MxIKWR5tK","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511959813,"user_tz":-330,"elapsed":25,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"93ceb01c-1fbe-414b-9e5f-274a0f13f7ef"},"source":["feature_names = df_features.columns\n","view_top_features(clf, feature_names)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Shared_Cluster_id_fof: 0.18\n","Friend_Friend_Sharing_Likelihood: 0.13\n","FoF_PageRank: 0.11\n","Profile_ID_PageRank: 0.11\n","Profile_ID_Friend_Sharing_Likelihood: 0.10\n","FoF_Friend_Sharing_Likelihood: 0.10\n","FoF_Edge_Count: 0.08\n","Friend_PageRank: 0.07\n","Profile_ID_Edge_Count: 0.07\n","Friend_Edge_Count: 0.06\n"]}]},{"cell_type":"markdown","metadata":{"id":"IYdi9vJ7R5tK"},"source":["One of our new features ranks quite highly.Nonetheless, the model is incomplete. An f-measure of 0.49 is not acceptable. We need to incorporate features from the profiles stored within `df_profiles`.\n","\n","## Adding Profile Features to the Model\n","\n","\n","Our aim is to incorporate the profile attributes of _Sex_, _Relationship_Status_, _Major_, _Dorm_ and _Year_ into our feature matrix. Based on our experience with the network data, there are three ways in which we can do this:\n","1. Exact Value Extraction.\n"," * We can store the exact value of the profile feature associated with each of the three profile-id columns in `df_obs`.\n"," \n","2. Equivalence Comparison\n"," * Given a profile attribute, we can carry-out a pairwise comparison of the attribute across all three profile-id columns in `df_obs`. For each comparison we would return a boolean feature demarcating whether the attribute is equal within the two columns.\n"," \n","3. Size:\n"," * Given a profile attribute, we can return the number of profiles that share that attribute.\n"," \n"," \n","Let's apply Exact Value Extraction to _Sex_, _Relationship_Status_ and _Year_. \n","\n","**Adding exact-value profile features**"]},{"cell_type":"code","metadata":{"id":"7Z1N3ya7R5tL","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511961540,"user_tz":-330,"elapsed":5,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"34098105-1dde-4f33-ac2a-9330be9558cb"},"source":["attributes = ['Sex', 'Relationship_Status', 'Year']\n","for attribute in attributes:\n"," features = {f'{col}_{attribute}_Value': [] for col in cols}\n"," for node_ids in df_obs[cols].values:\n"," for node, feature_name in zip(node_ids, features.keys()):\n"," att_value = G.nodes[node][attribute]\n"," features[feature_name].append(att_value)\n"," \n"," X = update_features(features)\n"," \n","f_measure, clf = evaluate(X, y)\n","print(f\"The f-measure is {f_measure:0.2f}\") "],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The f-measure is 0.74\n"]}]},{"cell_type":"markdown","metadata":{"id":"1DyXSFThR5tL"},"source":["Wow! The f-measure dramatically increased from 0.49 to 0.74! The profile features have provided a very valuable signal, but we can still do better. We need to incorporate information from the _Major_ and _Dorm_ attributes. Equivalence Comparison is an excellent way to do this.\n","\n","**Adding equivalence-comparison profile features**"]},{"cell_type":"code","metadata":{"id":"P33DntlfR5tL","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511962707,"user_tz":-330,"elapsed":700,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"6cd41d91-8838-4457-9d67-332d44420ba0"},"source":["attributes = ['Major', 'Dorm']\n","for attribute in attributes:\n"," features = {f'Shared_{attribute}_{e}': []\n"," for e in ['id_f', 'id_fof', 'f_fof']}\n"," for node_ids in df_obs[cols].values:\n"," att_id, att_f, att_fof = [G.nodes[n][attribute] \n"," for n in node_ids]\n"," features[f'Shared_{attribute}_id_f'].append(int(att_id == att_f))\n"," features[f'Shared_{attribute}_id_fof'].append(int(att_id == att_fof))\n"," features[f'Shared_{attribute}_f_fof'].append(int(att_f == att_fof))\n"," \n"," X = update_features(features)\n"," \n","f_measure, clf = evaluate(X, y)\n","print(f\"The f-measure is {f_measure:0.2f}\") "],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The f-measure is 0.82\n"]}]},{"cell_type":"markdown","metadata":{"id":"gg7jh64TR5tM"},"source":["Incorporating the _Major_ and _Dorm_ attributes has improved model performance. Now lets consider adding _Major_ and _Dorm Size_ into the mix. We can count the number of students associated with each major / dorm, and include this count as one of our features. However, we need to be careful. As we previously discussed, our trained model can cheat by utilizing size as a substitute for a category id. \n","\n","**Adding size-related profile features**"]},{"cell_type":"code","metadata":{"id":"xeuLHwSPR5tM","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511963980,"user_tz":-330,"elapsed":585,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"10d8f7a3-7386-4843-a0a5-0215e7c5a8fe"},"source":["from collections import Counter\n","\n","for attribute in ['Major', 'Dorm']:\n"," counter = Counter(df_profile[attribute].values)\n"," att_to_size = {k: v \n"," for k, v in counter.items()}\n"," features = {f'{col}_{attribute}_Size': [] for col in cols}\n"," for node_ids in df_obs[cols].values:\n"," for node, feature_name in zip(node_ids, features.keys()):\n"," size = att_to_size[G.nodes[node][attribute]]\n"," features[feature_name].append(size)\n"," \n"," \n"," X = update_features(features)\n"," \n","f_measure, clf = evaluate(X, y)\n","print(f\"The f-measure is {f_measure:0.2f}\") "],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The f-measure is 0.85\n"]}]},{"cell_type":"markdown","metadata":{"id":"HbdlsHoxR5tM"},"source":["Performance has increased from 0.82 to 0.85. The introduction of size has impacted our model. Lets dive deeper into that impact. We'll start by printing out the feature importance scores.\n","\n","**Ranking features by their importance score**"]},{"cell_type":"code","metadata":{"id":"r-eKmdWtR5tM","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511963981,"user_tz":-330,"elapsed":9,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"3572c480-c5b2-4374-c0b4-04fc9387102b"},"source":["feature_names = df_features.columns.values\n","view_top_features(clf, feature_names)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["FoF_Dorm_Size: 0.25\n","Shared_Cluster_id_fof: 0.16\n","Shared_Dorm_id_fof: 0.05\n","FoF_PageRank: 0.04\n","Profile_ID_Major_Size: 0.04\n","FoF_Major_Size: 0.04\n","FoF_Edge_Count: 0.04\n","Profile_ID_PageRank: 0.03\n","Profile_ID_Friend_Sharing_Likelihood: 0.03\n","Friend_Friend_Sharing_Likelihood: 0.03\n","Friend_Edge_Count: 0.03\n","Shared_Major_id_fof: 0.03\n","FoF_Friend_Sharing_Likelihood: 0.02\n","Friend_PageRank: 0.02\n","Profile_ID_Dorm_Size: 0.02\n","Profile_ID_Edge_Count: 0.02\n","Profile_ID_Sex_Value: 0.02\n","Friend_Major_Size: 0.02\n","Profile_ID_Relationship_Status_Value: 0.02\n","FoF_Sex_Value: 0.01\n","Friend_Dorm_Size: 0.01\n","Profile_ID_Year_Value: 0.01\n","Friend_Sex_Value: 0.01\n","Shared_Major_id_f: 0.01\n","Friend_Relationship_Status_Value: 0.01\n","Friend_Year_Value: 0.01\n"]}]},{"cell_type":"markdown","metadata":{"id":"mLJ29m_nR5tM"},"source":["The feature importance scores are dominated by two features; _FoF_Dorm_Size_ and _Shared_Cluster_id_fof_. The presence of _FoF_Dorm_Size_ is a bit concerning. As we've discussed, a single dorm dominates over 50% of the network data. Is our model simply memorizing that dorm based on its size? We can find out by actually visualizing a trained decision tree. \n","\n","**Displaying the top branches of the tree**"]},{"cell_type":"code","metadata":{"id":"45d4i0-qR5tN","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511964952,"user_tz":-330,"elapsed":6,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"8a6c0b62-cb32-4306-bf84-4423b6d1f9ec"},"source":["from sklearn import tree\n","\n","clf_depth2 = DecisionTreeClassifier(max_depth=2)\n","clf_depth2.fit(X, y)\n","text_tree = tree.export_text(clf_depth2, feature_names=list(feature_names))\n","print(text_tree)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["|--- FoF_Dorm_Size <= 278.50\n","| |--- Shared_Cluster_id_fof <= 0.50\n","| | |--- class: 0\n","| |--- Shared_Cluster_id_fof > 0.50\n","| | |--- class: 0\n","|--- FoF_Dorm_Size > 278.50\n","| |--- Shared_Cluster_id_fof <= 0.50\n","| | |--- class: 0\n","| |--- Shared_Cluster_id_fof > 0.50\n","| | |--- class: 1\n","\n"]}]},{"cell_type":"markdown","metadata":{"id":"Pt_XS2LFR5tN"},"source":["According to the the tree, the most important signal is whether _FoF_Dorm_Size_ is less than 279. This begs the question, how many dorms contain at-least 279 students? \n","\n","**Checking dorms with at-least 279 students**"]},{"cell_type":"code","metadata":{"id":"IJYLfO6vR5tN","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511967128,"user_tz":-330,"elapsed":7,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"92494656-88b6-4060-c6c9-f27e110a2b2d"},"source":["counter = Counter(df_profile.Dorm.values)\n","for dorm, count in counter.items():\n"," if count < 279:\n"," continue\n"," \n"," print(f\"Dorm {dorm} holds {count} students.\")"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Dorm 12 holds 2739 students.\n","Dorm 1 holds 413 students.\n"]}]},{"cell_type":"markdown","metadata":{"id":"9gWCZH6sR5tN"},"source":["Just two of the 15 dorms contain more than 279 FriendHook-registered students. Essentially, our model relies on the two most-populous dorms to make its decisions. This might not generalize to other college campuses. For instance, consider a campus whose dormitories are smaller, and hold 200 students at the most. The model will completely fail to predict user-behavior in this instance. \n","\n","Perhaps we could try deleting the size-related features while also adjusting our choice of classifier. There is a slight chance that we'll achieve comparable performance without relying on dorm size. This is unlikely but is still worth trying. \n","\n","**Deleting all size-related features**"]},{"cell_type":"code","metadata":{"id":"zwO2A2hZR5tQ"},"source":["X_with_sizes = X.copy()\n","X = delete_features(df_features, regex=r'_Size')"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"eB27CUnCR5tQ"},"source":["## Optimizing Performance Across a Steady Set of Features\n","\n","Will switching the model-type from a Decision tree to a Forest improve performance outcome? Lets find out.\n","\n","**Training and evaluating a Random Forest classifier**"]},{"cell_type":"code","metadata":{"id":"cw7-0shbR5tQ","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511976583,"user_tz":-330,"elapsed":1449,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"4e558a1c-f0d0-4fbe-fa91-4b5fd8212cf8"},"source":["np.random.seed(0)\n","from sklearn.ensemble import RandomForestClassifier\n","f_measure, clf = evaluate(X, y, model_type=RandomForestClassifier)\n","print(f\"The f-measure is {f_measure:0.2f}\") "],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The f-measure is 0.75\n"]}]},{"cell_type":"markdown","metadata":{"id":"8AlbUwndR5tR"},"source":["\n","Switching the type of model has not helped. Perhaps instead we can boost performance by optimizing on the hyperparameters? Within this book, we've focused on single Decision tree hyperparameter; max depth. Will limiting the depth improve our predictions? Lets quickly check using a simple grid search. \n","\n","**Optimizing max depth using grid search**"]},{"cell_type":"code","metadata":{"id":"7G7rA7LFR5tR","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511980785,"user_tz":-330,"elapsed":4208,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"d20f5aa8-8bcf-4412-89af-1b30a2f6c2fc"},"source":["from sklearn.model_selection import GridSearchCV\n","np.random.seed(0)\n","\n","hyperparams = {'max_depth': list(range(1, 100)) + [None]}\n","clf_grid = GridSearchCV(DecisionTreeClassifier(), hyperparams, \n"," scoring='f1_macro', cv=2)\n","clf_grid.fit(X, y)\n","best_f = clf_grid.best_score_\n","best_depth = clf_grid.best_params_['max_depth']\n","print(f\"A maximized f-measure of {best_f:.2f} is achieved when \"\n"," f\"max_depth equals {best_depth}\") "],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["A maximized f-measure of 0.84 is achieved when max_depth equals 5\n"]}]},{"cell_type":"markdown","metadata":{"id":"GqNB0WiMR5tR"},"source":["Setting `max_depth` to 5 improves the f-measure from from 0.82 to 0.84. This level of performance is comperable with our Dorm-size dependent model. Of course, we cannot make a fair comparison without first running a grid search on the size-inclusive `X_with_size` feature-matrix. Will optimizing on `X_with_size` yield an even better classifier? Lets find out.\n","\n","**Applying grid search to size-dependent training data**"]},{"cell_type":"code","metadata":{"id":"ZE-wPb7NR5tR","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511985998,"user_tz":-330,"elapsed":5217,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"0b52b3de-fedf-49c6-a60b-7f2409643d4d"},"source":["np.random.seed(0)\n","clf_grid.fit(X_with_sizes, y)\n","best_f = clf_grid.best_score_\n","best_depth = clf_grid.best_params_['max_depth']\n","print(f\"A maximized f-measure of {best_f:.2f} is achieved when \"\n"," f\"max_depth equals {best_depth}\") "],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["A maximized f-measure of 0.85 is achieved when max_depth equals 6\n"]}]},{"cell_type":"markdown","metadata":{"id":"JxspNBOWR5tS"},"source":["The grid search did not improve performance on `X_with_size`. Thus, we can conclude that with the right choice of max-depth, both the size-dependent and independent models perform with approximately equal quality. Consequently, we can train a generalizable, size-independent model without sacrificing perfomance. \n","\n","**Training a Decision tree with `max_depth` set to 5**"]},{"cell_type":"code","metadata":{"id":"ZWDYceBcR5tS","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511986000,"user_tz":-330,"elapsed":25,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"773c8799-e098-4b3c-f027-676d05853521"},"source":["clf = DecisionTreeClassifier(max_depth=5)\n","clf.fit(X, y)"],"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["DecisionTreeClassifier(max_depth=5)"]},"metadata":{},"execution_count":52}]},{"cell_type":"markdown","metadata":{"id":"w1MMvAJBR5tS"},"source":["## Interpreting the Trained Model\n","\n","Lets print our model's feature importance scores.\n","\n","**Ranking features by their importance score**"]},{"cell_type":"code","metadata":{"id":"zf2YWB5HR5tS","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511991446,"user_tz":-330,"elapsed":400,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"9a942d24-ed85-4650-85f6-0d82c54cfb6c"},"source":["feature_names = df_features.columns\n","view_top_features(clf, feature_names)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Shared_Dorm_id_fof: 0.42\n","Shared_Cluster_id_fof: 0.29\n","Shared_Major_id_fof: 0.10\n","Shared_Dorm_f_fof: 0.06\n","Profile_ID_Relationship_Status_Value: 0.04\n","Profile_ID_Sex_Value: 0.04\n","Friend_Edge_Count: 0.02\n","Friend_PageRank: 0.01\n","Shared_Dorm_id_f: 0.01\n"]}]},{"cell_type":"markdown","metadata":{"id":"IQ2x600eR5tT"},"source":["Only nine important features remain. Only three features have an importance score that's at or above 0.10. These are `Shared_Dorm_id_fof`, `Shared_Cluster_id_fof`, and `Shared_Major_id_fof`. Thus, the model is primarily driven by the following three questions:\n","\n","1. Do the the user and the friend-of-friend share a dormitory? Yes or no?\n","2. Do the the user and the friend-of-friend share a social group? Yes or no?\n","3. Do the the user and the friend-of-friend share a major? Yes or no?\n","\n","Intuitively, if the answers to all three questions are _Yes_, then the user and the friend-of-a-friend are more likely to connect on FriendHook. Lets test this intutition, by displaying the tree. \n","\n","**Displaying the top branches of the tree**"]},{"cell_type":"code","metadata":{"id":"EsbpNSHhR5tT","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511991984,"user_tz":-330,"elapsed":8,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"2d67aaf9-26e9-4319-c7d9-5f5bedee9790"},"source":["clf_depth3 = DecisionTreeClassifier(max_depth=3)\n","clf_depth3.fit(X, y)\n","text_tree = tree.export_text(clf_depth3, \n"," feature_names=list(feature_names))\n","print(text_tree)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["|--- Shared_Dorm_id_fof <= 0.50\n","| |--- Shared_Cluster_id_fof <= 0.50\n","| | |--- Shared_Major_id_fof <= 0.50\n","| | | |--- class: 0\n","| | |--- Shared_Major_id_fof > 0.50\n","| | | |--- class: 0\n","| |--- Shared_Cluster_id_fof > 0.50\n","| | |--- Shared_Major_id_fof <= 0.50\n","| | | |--- class: 0\n","| | |--- Shared_Major_id_fof > 0.50\n","| | | |--- class: 1\n","|--- Shared_Dorm_id_fof > 0.50\n","| |--- Shared_Cluster_id_fof <= 0.50\n","| | |--- Profile_ID_Sex_Value <= 0.50\n","| | | |--- class: 0\n","| | |--- Profile_ID_Sex_Value > 0.50\n","| | | |--- class: 2\n","| |--- Shared_Cluster_id_fof > 0.50\n","| | |--- Shared_Dorm_f_fof <= 0.50\n","| | | |--- class: 1\n","| | |--- Shared_Dorm_f_fof > 0.50\n","| | | |--- class: 1\n","\n"]}]},{"cell_type":"markdown","metadata":{"id":"xaLpaqqGR5tT"},"source":["\n","The model's logic is very straightforward. Users who share social groups and living spaces or study-schedules are more likely to connect. There's nothing suprising about that. What is suprising is how the _Sex_ feature drives _Class 2_ label prediction. According to our tree, rejection is more likeley when:\n","\n","1. The users share a dorm but are not in the same social group.\n","2. The request sender is of a certain specific sex.\n","\n","Of course, we know that _Class 2_ labels are fairly sparse within our data. Perhaps the model's predictions are caused by random noise arising from the sparse sampling? Lets quickly check how well we predict rejection. \n","\n","**Evaluating a rejection classifier**"]},{"cell_type":"code","metadata":{"id":"UZdrRIOOR5tT","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511993082,"user_tz":-330,"elapsed":7,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"27da7635-14a0-4bad-a6d9-ad50646372b0"},"source":["y_reject = y *(y == 2)\n","f_measure, clf_reject = evaluate(X, y_reject, max_depth=5)\n","print(f\"The f-measure is {f_measure:0.2f}\") "],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The f-measure is 0.97\n"]}]},{"cell_type":"markdown","metadata":{"id":"UuGMqc8CR5tU"},"source":["Wow, the f-measure is actually very high! We can predict rejection very well, despite the sparsity of data. What features drive rejection? Lets check by printing the new feature importance scores.\n","\n","**Ranking features by their importance score**"]},{"cell_type":"code","metadata":{"id":"yjMg-212R5tU","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511994583,"user_tz":-330,"elapsed":10,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"f086a958-3cff-4fd8-954d-b9b69a30b307"},"source":["view_top_features(clf_reject, feature_names)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Profile_ID_Sex_Value: 0.40\n","Profile_ID_Relationship_Status_Value: 0.24\n","Shared_Major_id_fof: 0.21\n","Shared_Cluster_id_fof: 0.10\n","Shared_Dorm_id_fof: 0.05\n"]}]},{"cell_type":"markdown","metadata":{"id":"Vvi2S_xRR5tU"},"source":["Interesting! Rejection is primarily driven by the user's _Sex_ and _Relationship_Status_ attributes. Lets visualize the trained tree to learn more.\n","\n","**Displaying the rejection-predicting tree**"]},{"cell_type":"code","metadata":{"id":"iY3lwtWWR5tU","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637511995784,"user_tz":-330,"elapsed":9,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"84153145-1545-4ddc-9f00-335d216675ca"},"source":["text_tree = tree.export_text(clf_reject, \n"," feature_names=list(feature_names))\n","print(text_tree)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["|--- Shared_Cluster_id_fof <= 0.50\n","| |--- Shared_Major_id_fof <= 0.50\n","| | |--- Shared_Dorm_id_fof <= 0.50\n","| | | |--- class: 0\n","| | |--- Shared_Dorm_id_fof > 0.50\n","| | | |--- Profile_ID_Relationship_Status_Value <= 2.50\n","| | | | |--- class: 0\n","| | | |--- Profile_ID_Relationship_Status_Value > 2.50\n","| | | | |--- Profile_ID_Sex_Value <= 0.50\n","| | | | | |--- class: 0\n","| | | | |--- Profile_ID_Sex_Value > 0.50\n","| | | | | |--- class: 2\n","| |--- Shared_Major_id_fof > 0.50\n","| | |--- Profile_ID_Sex_Value <= 0.50\n","| | | |--- class: 0\n","| | |--- Profile_ID_Sex_Value > 0.50\n","| | | |--- Profile_ID_Relationship_Status_Value <= 2.50\n","| | | | |--- class: 0\n","| | | |--- Profile_ID_Relationship_Status_Value > 2.50\n","| | | | |--- class: 2\n","|--- Shared_Cluster_id_fof > 0.50\n","| |--- class: 0\n","\n"]}]},{"cell_type":"markdown","metadata":{"id":"c844Hq5RR5tV"},"source":["According to the tree, individuals with _Sex Category 1_ and _Relationship Status Category 3_ are sending friend-requests to people outside their social group. These friend requests are likely to get rejected. Of course, we don't know the identify of the categories that lead to rejection. However, as scientists, we still speculate. Given what we know about human nature, it wouldn't be suprising this behavior is driven by single men. Perhaps they are trying to connect with women outside their social circle, in order to get a date? If, so then the request will probably be rejected. Again, all this is speculation. However, this hypothesis is worth discussing with the product managers at FriendHook. If our hypothesis is correct, then certain changes should be introduced to the product. More steps could be taken to limit unwanted dating requests. Alternatively, new product changes could be added that make easier for single people to connect."]},{"cell_type":"markdown","metadata":{"id":"lYhpcF49VW8Q"},"source":["In this case study, we have agonized over keeping our model generalizable. A model that does not generalize beyond the training set is worthless, even if the performance score seems high. Unfortunately, it’s hard to know whether a model can generalize until it’s tested on external data. But we can try to remain aware of hidden biases that won’t generalize well to other datasets. Failure to do so can yield serious consequences. Consider the following true story.\n","\n","For many years, machine learning researchers have tried to automate the field of radiology. In radiology, trained doctors examine medical images (such as X-rays) to diagnose disease. This can be treated as a supervised learning problem in which the images are features and the diagnoses are class labels. By the year 2016, multiple radiology models were published in the scientific literature. Each published model was supposed to be highly accurate based on internal evaluation. That year, leading machine learning researchers publicly declared that “we should stop training radiologists” and that “radiologists should be worried about their jobs.” Four years later, the negative publicity had led to a worldwide radiologist shortage—medical students were reluctant to enter a field that seemed destined for full automation. But by 2020, the promise of automation had failed to materialize. Most of the published models performed very poorly on new data. Why? Well, it turns out that imaging outputs differ from hospital to hospital. Different hospitals use slightly different lighting and different settings on their imaging machines. Thus, a model trained at Hospital A could not generalize well to Hospital B. Despite their seemingly high performance scores, the models were not fit for generalized use. The machine learning researchers had been too optimistic; they failed to take into account the biases inherent in their data. These failures inadvertently led to a crisis in the medical community. A more thoughtful evaluation of generalizability could have prevented this from happening."]},{"cell_type":"markdown","metadata":{"id":"Y7fRvG64F0YF"},"source":["## Summary\n","\n","- Superior machine learning algorithms do not necessarily work in every situation. Our decision tree model outperformed our random forest model, even though random forests are considered superior in the literature. We should never blindly assume that a model will always work well in every possible scenario. Instead, we should intelligently calibrate our model choice based on the specifics of the problem.\n","- Proper feature selection is less of a science and more of an art. We cannot always know in advance which features will boost a model’s performance. However, the commonsense integration of diverse and interesting features into our model should eventually improve prediction quality.\n","- We should pay careful attention to the features we feed into our model. Otherwise, the model may not generalize to other datasets.\n","- Proper hyperparameter optimization can sometimes significantly boost a model’s performance.\n","- Occasionally, it seems like nothing is working and our data is simply insufficient. However, with grit and perseverance, we can eventually yield meaningful resources. Remember, a good data scientist should never give up until they have exhausted every possible avenue of analysis."]},{"cell_type":"markdown","metadata":{"id":"a9khCVuLUnzd"},"source":["---"]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"Mq6Q1HzjUnzd","executionInfo":{"status":"ok","timestamp":1637512032091,"user_tz":-330,"elapsed":3739,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"579d9d3d-a4d7-498f-c8b6-280a436d464f"},"source":["!pip install -q watermark\n","%reload_ext watermark\n","%watermark -a \"Sparsh A.\" -m -iv -u -t -d"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Author: Sparsh A.\n","\n","Last updated: 2021-11-21 16:27:10\n","\n","Compiler : GCC 7.5.0\n","OS : Linux\n","Release : 5.4.104+\n","Machine : x86_64\n","Processor : x86_64\n","CPU cores : 2\n","Architecture: 64bit\n","\n","re : 2.2.1\n","numpy : 1.19.5\n","IPython : 5.5.0\n","markov_clustering: 0.0.6.dev0\n","networkx : 2.6.3\n","pandas : 1.1.5\n","sklearn : 0.0\n","matplotlib : 3.2.2\n","\n"]}]},{"cell_type":"markdown","metadata":{"id":"SLUgXbkjUnze"},"source":["---"]}]}