{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"1. Import bibliotek","metadata":{}},{"cell_type":"code","source":"from pathlib import Path\nimport pandas as pd\nimport numpy as np\nimport operator\nfrom random import randrange","metadata":{"execution":{"iopub.status.busy":"2022-06-03T18:04:53.097884Z","iopub.execute_input":"2022-06-03T18:04:53.098487Z","iopub.status.idle":"2022-06-03T18:04:53.103947Z","shell.execute_reply.started":"2022-06-03T18:04:53.098408Z","shell.execute_reply":"2022-06-03T18:04:53.103045Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"2. Wczytanie zbioru danych","metadata":{}},{"cell_type":"markdown","source":"Transakcje:","metadata":{}},{"cell_type":"code","source":"data_dir = Path('../input/h-and-m-personalized-fashion-recommendations')\ntransactions_df = pd.read_csv(data_dir/'transactions_train.csv')\nprint(len(transactions_df))\ntransactions_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-06-03T18:45:17.908654Z","iopub.execute_input":"2022-06-03T18:45:17.908942Z","iopub.status.idle":"2022-06-03T18:46:30.209711Z","shell.execute_reply.started":"2022-06-03T18:45:17.908913Z","shell.execute_reply":"2022-06-03T18:46:30.208778Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Podział transakcji na testowe i walidacyjne","metadata":{}},{"cell_type":"code","source":"#validation_df=transactions[transactions['t_dat']>='2020-09-01']\n#validation_df.head()\n#transactions=transactions[transactions['t_dat']<'2020-09-01']\nvalidation_df=transactions_df[transactions_df['t_dat']>='2020-05-01']\nvalidation_df.head()\ntransactions=transactions_df[transactions_df['t_dat']<'2020-05-01']\nprint(len(validation_df))\nprint(len(transactions))","metadata":{"execution":{"iopub.status.busy":"2022-06-03T18:47:35.752335Z","iopub.execute_input":"2022-06-03T18:47:35.753359Z","iopub.status.idle":"2022-06-03T18:47:41.370418Z","shell.execute_reply.started":"2022-06-03T18:47:35.753305Z","shell.execute_reply":"2022-06-03T18:47:41.369252Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Klienci:","metadata":{}},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"customer_df = pd.read_csv(data_dir/'customers.csv')\nprint(len(customer_df))\ncustomer_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-06-03T18:47:50.269084Z","iopub.execute_input":"2022-06-03T18:47:50.269778Z","iopub.status.idle":"2022-06-03T18:47:56.450557Z","shell.execute_reply.started":"2022-06-03T18:47:50.269722Z","shell.execute_reply":"2022-06-03T18:47:56.44953Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Artykuły:","metadata":{}},{"cell_type":"code","source":"articles_df = pd.read_csv(data_dir/'articles.csv')\nprint(len(articles_df))\narticles_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-06-03T18:47:59.730374Z","iopub.execute_input":"2022-06-03T18:47:59.730755Z","iopub.status.idle":"2022-06-03T18:48:01.057165Z","shell.execute_reply.started":"2022-06-03T18:47:59.730715Z","shell.execute_reply":"2022-06-03T18:48:01.056099Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Ustalanie wartości dodatkowych zmiennych","metadata":{}},{"cell_type":"code","source":"customer_basket=transactions.groupby(['customer_id'])['price'].mean()\ncustomer_basket.head()","metadata":{"execution":{"iopub.status.busy":"2022-06-03T18:48:14.603615Z","iopub.execute_input":"2022-06-03T18:48:14.603939Z","iopub.status.idle":"2022-06-03T18:48:26.565488Z","shell.execute_reply.started":"2022-06-03T18:48:14.603884Z","shell.execute_reply":"2022-06-03T18:48:26.56399Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Określenie wartości parametrów","metadata":{}},{"cell_type":"code","source":"maxAge=customer_df.age.max()\nminAge=customer_df.age.min()\nmaxBasket=customer_basket.max()\nminBasket=customer_basket.min()\nprint(maxAge)\nprint(minAge)\nprint(maxBasket)\nprint(minBasket)\n","metadata":{"execution":{"iopub.status.busy":"2022-06-03T18:48:31.259256Z","iopub.execute_input":"2022-06-03T18:48:31.259557Z","iopub.status.idle":"2022-06-03T18:48:31.292973Z","shell.execute_reply.started":"2022-06-03T18:48:31.259527Z","shell.execute_reply":"2022-06-03T18:48:31.291562Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#funkcja oceny wieku\nclass Age:\n    \"\"\"Funkcje przynależności: young, addult, and senior.\"\"\"\n    \n    def __int__(self):\n        pass\n\n    def young(self, age):\n        \"\"\"Funkcja przynależności young.\"\"\"\n        if age < 24.0:\n            return 1.0\n        elif 24.0 <= age < 44.0:\n            return float((44-age)/20.0)\n        else:\n            return 0.0\n        \n    def adult(self, age):\n        \"\"\"Funkcja przynależności  dla adult.\"\"\"\n        if age <= 24 or age > 64:\n            return 0.0\n        elif 24 < age <= 34:\n            return float(age-24)/10.0\n        elif 34 < age <= 55:\n            return 1.0\n        elif 55 < age <= 64:\n            return (64-age)/10.0\n        \n    def senior(self, age):\n        \"\"\"Funkcja przynależności dla senior.\"\"\"\n        if age <= 44:\n            return 0.0\n        elif 44 < age <= 64:\n            return (age-44.0)/20.0\n        else:\n            return 1.0\n\n    def get_fuzzy_set(self, age):\n        \"\"\"Funkcja przynależności dla wieku.\"\"\"\n        return [self.young(age),\n                self.adult(age),\n                self.senior(age)]\n\n","metadata":{"execution":{"iopub.status.busy":"2022-06-03T18:48:34.791897Z","iopub.execute_input":"2022-06-03T18:48:34.792767Z","iopub.status.idle":"2022-06-03T18:48:34.802347Z","shell.execute_reply.started":"2022-06-03T18:48:34.792724Z","shell.execute_reply":"2022-06-03T18:48:34.801374Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Klasa określająca funkcje przynależności dla koszyka","metadata":{}},{"cell_type":"code","source":"class Basket:\n    \n    def __int__(value):\n        pass\n\n    def economical(self, value):\n        \"\"\"Funkcja przynależności economical\"\"\"\n        if value < 0.1:\n            return 1.0\n        elif 0.1 <= value < 0.4:\n            return (0.4-value)/0.3\n        else:\n            return 0.0\n        \n    def welthy(self, value):\n        \"\"\"Funkcja przynależności welthy\"\"\"\n        if value < 0.1:\n            return 0.0\n        elif 0.1 < value <= 0.4:\n            return (value-0.1)/0.3\n        else:\n            return 1.0\n\n    def get_fuzzy_set(self, value):\n        \"\"\"Get fuzzy set values of given price.\"\"\"\n        return [self.economical(value),\n                self.welthy(value)]\n","metadata":{"execution":{"iopub.status.busy":"2022-06-03T18:48:41.53285Z","iopub.execute_input":"2022-06-03T18:48:41.533196Z","iopub.status.idle":"2022-06-03T18:48:41.541466Z","shell.execute_reply.started":"2022-06-03T18:48:41.533159Z","shell.execute_reply":"2022-06-03T18:48:41.540422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"instancje klas","metadata":{}},{"cell_type":"code","source":"age=Age()\nbasket=Basket()","metadata":{"execution":{"iopub.status.busy":"2022-06-03T18:48:56.416672Z","iopub.execute_input":"2022-06-03T18:48:56.41742Z","iopub.status.idle":"2022-06-03T18:48:56.423301Z","shell.execute_reply.started":"2022-06-03T18:48:56.417372Z","shell.execute_reply":"2022-06-03T18:48:56.421995Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def euclidean_dist(list_a, list_b):\n    \"\"\"Odległość euklidesowa.\"\"\"\n    return np.linalg.norm(np.array(list_a) - np.array(list_b))","metadata":{"execution":{"iopub.status.busy":"2022-06-03T18:48:59.674641Z","iopub.execute_input":"2022-06-03T18:48:59.674928Z","iopub.status.idle":"2022-06-03T18:48:59.679939Z","shell.execute_reply.started":"2022-06-03T18:48:59.674899Z","shell.execute_reply":"2022-06-03T18:48:59.679148Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Policzenie podobieństwa pomiędzy klientami","metadata":{}},{"cell_type":"code","source":"def fuzzy_distance(c1, c2):\n    NO_OF_FEATURES=7\n    fuzzy_dis = [0] * NO_OF_FEATURES\n    ui=[c1[0],c1[1],c1[2],c1[3],c1[4],c1[6],c1[5]]\n    uj=[c2[0],c2[1],c2[2],c2[3],c2[4],c2[6],c2[5]]\n   \n    fuzzy_dis[0]=c2[0]\n    for i in range(1, NO_OF_FEATURES-1):\n        ui_gim = ui[i]\n        uj_gim = uj[i]\n        if str(ui_gim)==str(uj_gim) :\n            fuzzy_dis[i] = 0\n        else:\n            fuzzy_dis[i] = 1\n    result=[-1]*3\n    \"\"\"Client_Id\"\"\"\n    result[0]=fuzzy_dis[0]\n    \"\"\"Odległość Levenshteina\"\"\"\n    result[1]=fuzzy_dis[1]+fuzzy_dis[2]+fuzzy_dis[3]+fuzzy_dis[4]+fuzzy_dis[5]+fuzzy_dis[6]\n    \"\"\"Odległość Euklidesowa dla wieku i koszyka\"\"\"\n    if c1[0] in customer_basket and c2[0] in customer_basket:\n        basket1=customer_basket[c1[0]]\n        basket2=customer_basket[c2[0]] \n        if basket1>0 and basket2>0 and ui[i+1]>0 and uj[i+1]>0:\n            client1=age.get_fuzzy_set(ui[i+1])+basket.get_fuzzy_set(basket1)\n            client2=age.get_fuzzy_set(uj[i+1])+basket.get_fuzzy_set(basket2)\n            result[2]=euclidean_dist(client1,client2)\n\n    return result\n\n","metadata":{"execution":{"iopub.status.busy":"2022-06-03T18:49:03.325789Z","iopub.execute_input":"2022-06-03T18:49:03.32614Z","iopub.status.idle":"2022-06-03T18:49:03.338879Z","shell.execute_reply.started":"2022-06-03T18:49:03.326102Z","shell.execute_reply":"2022-06-03T18:49:03.337526Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Funkcja obliczająca dla podanego klienta podobieństwo do innych","metadata":{}},{"cell_type":"code","source":"\ndef calculate_values(clientid):\n    input_customer=customer_df[customer_df['customer_id']==clientid]\n    #print(input_customer)\n    calculateResult=[]\n    customersToCompare=customer_df.head(10000)#[customer_df['postal_code'].isin(input_customer.postal_code)]#.head(10000)#[(customer_df.customer_id.isin(transactions20190122.customer_id))]\n    #print('Customers to compare:'+str(len(customersToCompare)))\n    for _, cust in  input_customer.iterrows():\n        for _, value in customersToCompare.iterrows():\n            if type(cust.age) == int or float:\n                if type(value.age) == int or float:\n                    if not np.isnan(value.age):\n                        toAdd=fuzzy_distance(cust.to_numpy(),value.to_numpy())\n                        if toAdd[1]>0 and toAdd[2]>0 :\n                            toAdd.append(toAdd[1]+toAdd[2])\n                            calculateResult.append(toAdd)\n    return calculateResult;","metadata":{"execution":{"iopub.status.busy":"2022-06-03T19:11:05.228657Z","iopub.execute_input":"2022-06-03T19:11:05.229458Z","iopub.status.idle":"2022-06-03T19:11:05.241406Z","shell.execute_reply.started":"2022-06-03T19:11:05.229396Z","shell.execute_reply":"2022-06-03T19:11:05.237925Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Posortowanie klientów po podobieństwie i wybranie 100 pierwszych","metadata":{}},{"cell_type":"code","source":"\ndef get_similarCustomersSet(similarCustomers,k):\n    similar=sorted(similarCustomers, key=operator.itemgetter(3), reverse=False)[:k]\n    return similar\n    #print(podobni)","metadata":{"execution":{"iopub.status.busy":"2022-06-03T18:49:11.680678Z","iopub.execute_input":"2022-06-03T18:49:11.68098Z","iopub.status.idle":"2022-06-03T18:49:11.685901Z","shell.execute_reply.started":"2022-06-03T18:49:11.680933Z","shell.execute_reply":"2022-06-03T18:49:11.685141Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Pobranie towarów podobnych klientów. Trzeba wykluczyć towary już kupione. Jest raczej mało prawdopodobnym, że klient będzie kupował ten sam produkt typu odzież.","metadata":{}},{"cell_type":"code","source":"def get_articles_from_similarCustomersSet(customer,similarCustomersSet):\n    similarCustomersTransaction=transactions[(transactions.customer_id.isin(list(map(operator.itemgetter(0), similarCustomersSet))))]\n    customerTran=transactions[transactions['customer_id']==customer]\n    similarCustomersTransaction=similarCustomersTransaction[~similarCustomersTransaction['article_id'].isin(customerTran.article_id)]\n    return similarCustomersTransaction","metadata":{"execution":{"iopub.status.busy":"2022-06-03T18:49:16.891646Z","iopub.execute_input":"2022-06-03T18:49:16.892427Z","iopub.status.idle":"2022-06-03T18:49:16.898128Z","shell.execute_reply.started":"2022-06-03T18:49:16.892384Z","shell.execute_reply":"2022-06-03T18:49:16.897134Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Funkcja oceniająca jakość wyniku. Porównuje listę rekomendowanych towarów z towarami rzeczywiście kupionymi","metadata":{}},{"cell_type":"code","source":"def evaluation(result, validation):\n    if len(result)==0 :\n        return 0;\n    else:\n        return len([value for value in result if value in validation])/len(result)","metadata":{"execution":{"iopub.status.busy":"2022-06-03T18:49:19.980975Z","iopub.execute_input":"2022-06-03T18:49:19.981601Z","iopub.status.idle":"2022-06-03T18:49:19.986438Z","shell.execute_reply.started":"2022-06-03T18:49:19.981567Z","shell.execute_reply":"2022-06-03T18:49:19.985532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Metoda poniżej zwraca rekomendacje dla podanych klientów:","metadata":{}},{"cell_type":"code","source":"customersToCheck=pd.Series(np.intersect1d(pd.Series(validation_df['customer_id']),customer_basket.keys()))\nprint(len(customersToCheck))\nprint(len(customer_basket.keys()))\nprint(len(pd.Series(validation_df['customer_id'])))\nprint(similarCustomersCount)\n\nfor a in range(1,2):#wielkość setu rekomendacji *5\n    for s in range(1,2):#wielkość setu podobnych klientów *100\n        for x in range(100):\n            randomClient=randrange(0, len(customersToCheck), 1) \n            clienId=customersToCheck[randomClient]\n            #print('Recomendation for:')\n            #print(clienId)\n            calculateResult=calculate_values(clienId)\n\n            similarCustSet=get_similarCustomersSet(calculateResult,s*100)\n            #print('Similar customers:')\n            #print(similarCustSet[:10])\n            articles=get_articles_from_similarCustomersSet(clienId,similarCustSet)\n            #print('Articles for similar customers:')\n            #print(articles)\n            groupedArticles=articles.groupby('article_id')['article_id'].value_counts()\n            predictedArticles=groupedArticles.sort_values(ascending=False).nlargest(5*a)\n            #print('Grouped articles for similar customers:')\n            #print(predictedArticles)\n            predictedArticleList=[int(num[0]) for num in predictedArticles.keys().tolist()]\n            #print('Predicted article list:')\n            #print(predictedArticleList)\n            #print('Transaction from validation set:')\n            validationTransactionForCustomer=validation_df[validation_df['customer_id']==clienId]\n            #print(validationTransactionForCustomer)\n            validationArticlesForCustomer=validationTransactionForCustomer.article_id.unique().tolist()\n            #print('Articles from validation set:')\n            #print(validationArticlesForCustomer)\n\n            evaluation_result=evaluation(predictedArticles,validationArticlesForCustomer)\n            #print(rec_result)\n            #if(evaluation_result>0):\n            print('---------------------------------------------------------')\n            print('Recomendation for:'+clienId+'='+str(evaluation_result*100)+' %')\n            print('Predicted article list:')\n            print(predictedArticleList)\n            print('Articles from validation set:')\n            print(validationArticlesForCustomer)\n            #print(validationArticlesForCustomer)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}