Upload New File

parent e796e8e1
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"\n",
"data = pd.read_csv(\"men-products.csv\", delimiter=',', index_col=0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Ignore the tuple"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>total_missing</th>\n",
" <th>percent_missing</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>NAME</th>\n",
" <td>1</td>\n",
" <td>0.005</td>\n",
" </tr>\n",
" <tr>\n",
" <th>CATEGORY</th>\n",
" <td>0</td>\n",
" <td>0.000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>DESCRIPTION &amp; COLOR</th>\n",
" <td>0</td>\n",
" <td>0.000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>FABRIC</th>\n",
" <td>4833</td>\n",
" <td>24.165</td>\n",
" </tr>\n",
" <tr>\n",
" <th>IMAGE</th>\n",
" <td>0</td>\n",
" <td>0.000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>SIZE</th>\n",
" <td>3838</td>\n",
" <td>19.190</td>\n",
" </tr>\n",
" <tr>\n",
" <th>PRICE</th>\n",
" <td>0</td>\n",
" <td>0.000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>PRODUCT ID</th>\n",
" <td>0</td>\n",
" <td>0.000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>WEBSITE</th>\n",
" <td>0</td>\n",
" <td>0.000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>PRODUCT URL</th>\n",
" <td>0</td>\n",
" <td>0.000</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" total_missing percent_missing\n",
"NAME 1 0.005\n",
"CATEGORY 0 0.000\n",
"DESCRIPTION & COLOR 0 0.000\n",
"FABRIC 4833 24.165\n",
"IMAGE 0 0.000\n",
"SIZE 3838 19.190\n",
"PRICE 0 0.000\n",
"PRODUCT ID 0 0.000\n",
"WEBSITE 0 0.000\n",
"PRODUCT URL 0 0.000"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"missing_data = pd.DataFrame({'total_missing': data.isnull().sum(), 'percent_missing': (data.isnull().sum()/20000)*100})\n",
"missing_data"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>NAME</th>\n",
" <th>CATEGORY</th>\n",
" <th>DESCRIPTION &amp; COLOR</th>\n",
" <th>FABRIC</th>\n",
" <th>IMAGE</th>\n",
" <th>SIZE</th>\n",
" <th>PRICE</th>\n",
" <th>PRODUCT ID</th>\n",
" <th>WEBSITE</th>\n",
" <th>PRODUCT URL</th>\n",
" </tr>\n",
" <tr>\n",
" <th>SERIAL NO</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>U.S. Polo Assn. Men Brown Genuine Leather Two ...</td>\n",
" <td>accessories</td>\n",
" <td>U.S. Polo Assn. Men Brown Genuine Leather Two ...</td>\n",
" <td>Genuine leather</td>\n",
" <td>https://assets.myntassets.com/h_1440,q_100,w_1...</td>\n",
" <td>Height: 11.5 cm</td>\n",
" <td>809</td>\n",
" <td>1943420</td>\n",
" <td>Myntra</td>\n",
" <td>https://www.myntra.com/wallets/us-polo-assn/us...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Baggit Men Black Solid Two Fold Wallet</td>\n",
" <td>accessories</td>\n",
" <td>Baggit Men Black Solid Two Fold Wallet, Baggi...</td>\n",
" <td>PU</td>\n",
" <td>https://assets.myntassets.com/h_1440,q_100,w_1...</td>\n",
" <td>Height:</td>\n",
" <td>720</td>\n",
" <td>4608404</td>\n",
" <td>Myntra</td>\n",
" <td>https://www.myntra.com/wallets/baggit/baggit-m...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>HRX by Hrithik Roshan Men Grey Solid Baseball Cap</td>\n",
" <td>accessories</td>\n",
" <td>HRX By Hrithik Roshan Men Grey Solid Baseball ...</td>\n",
" <td>NaN</td>\n",
" <td>https://assets.myntassets.com/h_1440,q_100,w_1...</td>\n",
" <td>NaN</td>\n",
" <td>279</td>\n",
" <td>2178513</td>\n",
" <td>Myntra</td>\n",
" <td>https://www.myntra.com/caps/hrx-by-hrithik-ros...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Puma Unisex Grey Style Military Solid Baseball...</td>\n",
" <td>accessories</td>\n",
" <td>Puma Unisex Grey Style Military Solid Baseball...</td>\n",
" <td>NaN</td>\n",
" <td>https://assets.myntassets.com/h_1440,q_100,w_1...</td>\n",
" <td>NaN</td>\n",
" <td>499</td>\n",
" <td>6699035</td>\n",
" <td>Myntra</td>\n",
" <td>https://www.myntra.com/caps/puma/puma-unisex-g...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>FabSeasons Beige Solid Scarf</td>\n",
" <td>accessories</td>\n",
" <td>FabSeasons Beige Solid Scarf, FabSeasons, Scar...</td>\n",
" <td>Acrylic</td>\n",
" <td>https://assets.myntassets.com/h_1440,q_100,w_1...</td>\n",
" <td>Length:0.9 m</td>\n",
" <td>449</td>\n",
" <td>2439658</td>\n",
" <td>Myntra</td>\n",
" <td>https://www.myntra.com/scarves/fabseasons/fabs...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>Ed Hardy Men Black Embellished Belt</td>\n",
" <td>accessories</td>\n",
" <td>Ed Hardy Men Black Embellished Belt, Ed Hardy...</td>\n",
" <td>Leather</td>\n",
" <td>https://assets.myntassets.com/h_1440,q_100,w_1...</td>\n",
" <td>Width: 3.7 cm</td>\n",
" <td>1199</td>\n",
" <td>2238752</td>\n",
" <td>Myntra</td>\n",
" <td>https://www.myntra.com/belts/ed-hardy/ed-hardy...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>Roadster Men Tan Brown Leather Belt</td>\n",
" <td>accessories</td>\n",
" <td>Roadster Men Tan Brown Leather Belt, Roadster,...</td>\n",
" <td>Leather</td>\n",
" <td>https://assets.myntassets.com/h_1440,q_100,w_1...</td>\n",
" <td>Width: 4 cm</td>\n",
" <td>419</td>\n",
" <td>2975974</td>\n",
" <td>Myntra</td>\n",
" <td>https://www.myntra.com/belts/roadster/roadster...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>Peora Silver-Toned Rhodium-Plated Stone-Studde...</td>\n",
" <td>accessories</td>\n",
" <td>Peora Silver Toned Rhodium Plated Stone Studde...</td>\n",
" <td>NaN</td>\n",
" <td>https://assets.myntassets.com/h_1440,q_100,w_1...</td>\n",
" <td>NaN</td>\n",
" <td>551</td>\n",
" <td>3006095</td>\n",
" <td>Myntra</td>\n",
" <td>https://www.myntra.com/ring/peora/peora-silver...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>Royal Enfield Unisex White Urban Trooper Helme...</td>\n",
" <td>accessories</td>\n",
" <td>Royal Enfield Unisex White Urban Trooper Helme...</td>\n",
" <td>NaN</td>\n",
" <td>https://assets.myntassets.com/h_1440,q_100,w_1...</td>\n",
" <td>NaN</td>\n",
" <td>3500</td>\n",
" <td>2242802</td>\n",
" <td>Myntra</td>\n",
" <td>https://www.myntra.com/helmets/royal-enfield/r...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>10</th>\n",
" <td>BuckleUp Men Black Leather Belt</td>\n",
" <td>accessories</td>\n",
" <td>BuckleUp Men Black Leather Belt, BuckleUp, Bel...</td>\n",
" <td>Leather</td>\n",
" <td>https://assets.myntassets.com/h_1440,q_100,w_1...</td>\n",
" <td>Width: 3.5 cm</td>\n",
" <td>517</td>\n",
" <td>1734718</td>\n",
" <td>Myntra</td>\n",
" <td>https://www.myntra.com/belts/buckleup/buckleup...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" NAME CATEGORY \\\n",
"SERIAL NO \n",
"1 U.S. Polo Assn. Men Brown Genuine Leather Two ... accessories \n",
"2 Baggit Men Black Solid Two Fold Wallet accessories \n",
"3 HRX by Hrithik Roshan Men Grey Solid Baseball Cap accessories \n",
"4 Puma Unisex Grey Style Military Solid Baseball... accessories \n",
"5 FabSeasons Beige Solid Scarf accessories \n",
"6 Ed Hardy Men Black Embellished Belt accessories \n",
"7 Roadster Men Tan Brown Leather Belt accessories \n",
"8 Peora Silver-Toned Rhodium-Plated Stone-Studde... accessories \n",
"9 Royal Enfield Unisex White Urban Trooper Helme... accessories \n",
"10 BuckleUp Men Black Leather Belt accessories \n",
"\n",
" DESCRIPTION & COLOR \\\n",
"SERIAL NO \n",
"1 U.S. Polo Assn. Men Brown Genuine Leather Two ... \n",
"2 Baggit Men Black Solid Two Fold Wallet, Baggi... \n",
"3 HRX By Hrithik Roshan Men Grey Solid Baseball ... \n",
"4 Puma Unisex Grey Style Military Solid Baseball... \n",
"5 FabSeasons Beige Solid Scarf, FabSeasons, Scar... \n",
"6 Ed Hardy Men Black Embellished Belt, Ed Hardy... \n",
"7 Roadster Men Tan Brown Leather Belt, Roadster,... \n",
"8 Peora Silver Toned Rhodium Plated Stone Studde... \n",
"9 Royal Enfield Unisex White Urban Trooper Helme... \n",
"10 BuckleUp Men Black Leather Belt, BuckleUp, Bel... \n",
"\n",
" FABRIC \\\n",
"SERIAL NO \n",
"1 Genuine leather \n",
"2 PU \n",
"3 NaN \n",
"4 NaN \n",
"5 Acrylic \n",
"6 Leather \n",
"7 Leather \n",
"8 NaN \n",
"9 NaN \n",
"10 Leather \n",
"\n",
" IMAGE SIZE \\\n",
"SERIAL NO \n",
"1 https://assets.myntassets.com/h_1440,q_100,w_1... Height: 11.5 cm \n",
"2 https://assets.myntassets.com/h_1440,q_100,w_1... Height: \n",
"3 https://assets.myntassets.com/h_1440,q_100,w_1... NaN \n",
"4 https://assets.myntassets.com/h_1440,q_100,w_1... NaN \n",
"5 https://assets.myntassets.com/h_1440,q_100,w_1... Length:0.9 m \n",
"6 https://assets.myntassets.com/h_1440,q_100,w_1... Width: 3.7 cm \n",
"7 https://assets.myntassets.com/h_1440,q_100,w_1... Width: 4 cm \n",
"8 https://assets.myntassets.com/h_1440,q_100,w_1... NaN \n",
"9 https://assets.myntassets.com/h_1440,q_100,w_1... NaN \n",
"10 https://assets.myntassets.com/h_1440,q_100,w_1... Width: 3.5 cm \n",
"\n",
" PRICE PRODUCT ID WEBSITE \\\n",
"SERIAL NO \n",
"1 809 1943420 Myntra \n",
"2 720 4608404 Myntra \n",
"3 279 2178513 Myntra \n",
"4 499 6699035 Myntra \n",
"5 449 2439658 Myntra \n",
"6 1199 2238752 Myntra \n",
"7 419 2975974 Myntra \n",
"8 551 3006095 Myntra \n",
"9 3500 2242802 Myntra \n",
"10 517 1734718 Myntra \n",
"\n",
" PRODUCT URL \n",
"SERIAL NO \n",
"1 https://www.myntra.com/wallets/us-polo-assn/us... \n",
"2 https://www.myntra.com/wallets/baggit/baggit-m... \n",
"3 https://www.myntra.com/caps/hrx-by-hrithik-ros... \n",
"4 https://www.myntra.com/caps/puma/puma-unisex-g... \n",
"5 https://www.myntra.com/scarves/fabseasons/fabs... \n",
"6 https://www.myntra.com/belts/ed-hardy/ed-hardy... \n",
"7 https://www.myntra.com/belts/roadster/roadster... \n",
"8 https://www.myntra.com/ring/peora/peora-silver... \n",
"9 https://www.myntra.com/helmets/royal-enfield/r... \n",
"10 https://www.myntra.com/belts/buckleup/buckleup... "
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data.head(10)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data.duplicated().sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Delete Columns "
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"del data['FABRIC']\n",
"del data['IMAGE']\n",
"del data['SIZE']\n",
"del data['WEBSITE']\n",
"del data['PRODUCT URL']\n",
"del data['PRICE']\n",
"del data['PRODUCT ID']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Rename Columns"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"data.rename(columns = {'DESCRIPTION & COLOR':'DESCRIPTION'}, inplace = True) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###### Karena Data dalam jumlah besar maka diambil sampel 10.000 data"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"data1 = data.sample(10000, random_state=1).copy()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# Rename kategori produk\n",
"data1.replace({'CATEGORY': \n",
" {'accessories': 'Accesories', \n",
" 'casual-shirts': 'Casual Shirts',\n",
" 'Men-Casual-Trousers': 'Men Casual Trousers',\n",
" 'formal-shirts': 'Formal Shirts',\n",
" 'Men-Formal-Trousers': 'Men Formal Trousers',\n",
" 'men-jackets-coats': 'Men Jackets Coats',\n",
" 'men-swimwear': 'Men Swimwear',\n",
" 'men-suits': 'Men Suits'}}, \n",
" inplace= True)# Punctuation Removal"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"88348"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data1.index = range(10000)\n",
"data1['NAME'].apply(lambda x: len(x.split(' '))).sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Punctuation Removal"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 Fort Collins Men Red Solid Padded Jacket\n",
"1 MANGO MAN Men Navy Blue Tailored Slim Fit Soli...\n",
"2 Arrow Men Navy Blue Tapered Fit Checked Formal...\n",
"3 Hanes Charcoal Grey Thermal TShirt\n",
"4 Hancock Men Blue Regular Fit Striped Formal Shirt\n",
"5 Tantra Men Black Printed Round Neck Tshirt\n",
"6 Aeropostale Men Blue Regular Fit MidRise Mildl...\n",
"7 ether Men Navy Blue Slim Fit Anti Microbial Co...\n",
"8 Roadster Men White Regular Fit MidRise Clean L...\n",
"9 Dollar Bigboss Pack of 3 Trunks MDTR03PO34\n",
"10 Moda Rapido Men Black Printed Polo Collar Tshirt\n",
"11 Louis Philippe Men Grey Regular Fit Self Desig...\n",
"12 Light Blue Mid Rise Skinny Fit Jeans\n",
"13 HIGHLANDER Men Olive Green Slim Fit Camouflage...\n",
"14 US Polo Assn Denim Co Men White Blue Slim Fit...\n",
"15 Levis Men Navy Blue Slim Fit Solid Casual Shirt\n",
"16 Louis Philippe Sport Men Charcoal Grey Solid T...\n",
"17 Killer Men Blue Regular Fit MidRise Clean Look...\n",
"18 Peter England Casuals Men Grey Slim Fit Solid ...\n",
"19 Arrow Men Grey Tapered Fit Solid Formal Trousers\n",
"20 V Dot Men Grey Slim Fit Self Design Formal Tro...\n",
"21 GESPO Men White Printed Round Neck Tshirt\n",
"22 SMAG Men Mustard Solid Lightweight Tailored Ja...\n",
"23 Jack Jones Men Black Slim Fit Solid Regular T...\n",
"24 Van Heusen Men Blue Regular Fit Solid Formal S...\n",
"25 Maniac Men Grey Solid VNeck Tshirt\n",
"26 HERENOW Men Blue Slim Fit MidRise Clean Look S...\n",
"27 Blackberrys Men Navy Blue Printed Casual Trousers\n",
"28 Moda Rapido Men White Printed Round Neck Longl...\n",
"29 Fort Collins Men Tan Brown Solid Biker Jacket\n",
"30 Fort Collins Men Rust Brown Solid Biker Jacket\n",
"31 ESPRIT Men Navy OffWhite Striped Round Neck T...\n",
"32 US Polo Assn Men Olive Green Regular Fit Solid...\n",
"33 Jockey Men Navy Blue Striped VNeck Tshirt\n",
"34 Indian Terrain Men Rust Red Solid Polo Collar ...\n",
"35 Pacific Gold Men Black Accessory Gift Set\n",
"36 WROGN Men Navy Solid Biker Jacket\n",
"37 LOCOMOTIVE Men Blue Slim Fit MidRise Clean Loo...\n",
"38 Blue Washed Slim Fit Jeans\n",
"39 LOCOMOTIVE Men Rust Printed Round Neck Tshirt\n",
"40 WROGN Men Olive Green Colourblocked Round Neck...\n",
"41 Killer Men Red Solid Polo Collar Tshirt\n",
"42 Van Heusen Men Blue Contemporary Regular Fit C...\n",
"43 Van Heusen Men Blue Slim Fit Solid Casual Shirt\n",
"44 Cottonworld Men Black Printed Round Neck Tshirt\n",
"45 Reebok Men Blue Athletic Graphic Printed Round...\n",
"46 Moda Rapido Men Black Olive Green Colourblock...\n",
"47 2GO Men Black Printed Polo Tshirt\n",
"48 Roadster Men Navy Blue Colourblocked Round Nec...\n",
"49 Knotyy Men Grey Colourblocked SelfDesign Beani...\n",
"Name: NAME, dtype: object\n"
]
}
],
"source": [
"data1['NAME'] = data1['NAME'].str.replace('[^\\w\\s]','')\n",
"# Hasil Punctuation Removal\n",
"print(data1[\"NAME\"].head(50))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Case Folding (Convert string to lower)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 fort collins men red solid padded jacket\n",
"1 mango man men navy blue tailored slim fit soli...\n",
"2 arrow men navy blue tapered fit checked formal...\n",
"3 hanes charcoal grey thermal tshirt\n",
"4 hancock men blue regular fit striped formal shirt\n",
"Name: NAME, dtype: object\n"
]
}
],
"source": [
"# mengubah ke huruf kecil\n",
"data1['NAME'] = data1['NAME'].str.lower()\n",
"print(data1['NAME'].head(5))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Remove Stopwords and Stemming"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"import re\n",
"from nltk.corpus import stopwords\n",
"import pandas as pd\n",
"from nltk.stem import PorterStemmer\n",
"from nltk.tokenize import sent_tokenize, word_tokenize\n",
"\n",
"def preprocess(raw_text):\n",
"\n",
" # keep only words\n",
" letters_only_text = re.sub(\"[^a-zA-Z]\", \" \", raw_text)\n",
"\n",
" # convert to lower case and split \n",
" words = letters_only_text.lower().split()\n",
"\n",
" # remove stopwords\n",
" stopword_set = set(stopwords.words(\"english\"))\n",
" meaningful_words = [w for w in words if w not in stopword_set]\n",
" \n",
" #stemmed words\n",
" ps = PorterStemmer()\n",
" stemmed_words = [ps.stem(word) for word in meaningful_words]\n",
" \n",
" #join the cleaned words in a list\n",
" cleaned_word_list = \" \".join(stemmed_words)\n",
" \n",
" return cleaned_word_list"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"data1['NAME'] = data1['NAME'].apply(lambda line : preprocess(line))"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>NAME</th>\n",
" <th>CATEGORY</th>\n",
" <th>DESCRIPTION</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>fort collin men red solid pad jacket</td>\n",
" <td>Men Jackets Coats</td>\n",
" <td>Fort Collins Men Red Solid Padded Jacket, For...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>mango man men navi blue tailor slim fit solid ...</td>\n",
" <td>Men Formal Trousers</td>\n",
" <td>MANGO MAN Men Navy Blue Tailored Slim Fit Soli...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>arrow men navi blue taper fit check formal tro...</td>\n",
" <td>Men Formal Trousers</td>\n",
" <td>Arrow Men Navy Blue Tapered Fit Checked Formal...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>hane charcoal grey thermal tshirt</td>\n",
" <td>Innerwear &amp; Sleapwear</td>\n",
" <td>Hanes Charcoal Grey Thermal T Shirt, Hanes, T...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>hancock men blue regular fit stripe formal shirt</td>\n",
" <td>Formal Shirts</td>\n",
" <td>Hancock Men Blue Regular Fit Striped Formal Sh...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" NAME CATEGORY \\\n",
"0 fort collin men red solid pad jacket Men Jackets Coats \n",
"1 mango man men navi blue tailor slim fit solid ... Men Formal Trousers \n",
"2 arrow men navi blue taper fit check formal tro... Men Formal Trousers \n",
"3 hane charcoal grey thermal tshirt Innerwear & Sleapwear \n",
"4 hancock men blue regular fit stripe formal shirt Formal Shirts \n",
"\n",
" DESCRIPTION \n",
"0 Fort Collins Men Red Solid Padded Jacket, For... \n",
"1 MANGO MAN Men Navy Blue Tailored Slim Fit Soli... \n",
"2 Arrow Men Navy Blue Tapered Fit Checked Formal... \n",
"3 Hanes Charcoal Grey Thermal T Shirt, Hanes, T... \n",
"4 Hancock Men Blue Regular Fit Striped Formal Sh... "
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data1.head()"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"import networkx as nx\n",
"import pandas as pd\n",
"import numpy as np\n",
"import random\n",
"from tqdm import tqdm\n",
"from sklearn.decomposition import PCA\n",
"\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###### Gabungan data pada CATEGORY dan NAME menjadi vocabulary"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###### Membangun graph menggunakan vocabulary"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"G = nx.from_pandas_edgelist(data1, \"CATEGORY\", \"NAME\", edge_attr=True, create_using=nx.Graph())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###### Memeriksa jumlah node dalam graph"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"8125"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(G)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###### Kami mendefinisikan fungsi yang akan mengambil node dan panjang path yang dilalui sebagai input. Fungsi akan berjalan melalui node yang terhubung dari input node yang ditentukan random walk. Lalu fungsi akan mengembalikan urutan node yang dilalui."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"def get_randomwalk(node, path_length):\n",
" \n",
" random_walk = [node]\n",
" \n",
" for i in range(path_length-1):\n",
" temp = list(G.neighbors(node))\n",
" temp = list(set(temp) - set(random_walk)) \n",
" if len(temp) == 0:\n",
" break\n",
"\n",
" random_node = random.choice(temp)\n",
" random_walk.append(random_node)\n",
" node = random_node\n",
" \n",
" return random_walk"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###### Contoh fungsi untuk: Men Formal Trousers"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['Men Formal Trousers', 'invictu men black slim fit solid formal trouser']"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"get_randomwalk('Men Formal Trousers', 10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###### Kami menentukan panjang path untuk dilintasi dengan nilai 10. Kami akan menangkap random walk untuk semua node dalam dataset kami."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"100%|████████████████████████████████████████████████████████████████████████████| 8125/8125 [00:06<00:00, 1289.47it/s]\n"
]
},
{
"data": {
"text/plain": [
"40625"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# get list of all nodes from the graph\n",
"all_nodes = list(G.nodes())\n",
"\n",
"random_walks = []\n",
"for n in tqdm(all_nodes):\n",
" for i in range(5):\n",
" random_walks.append(get_randomwalk(n,10))\n",
" \n",
"# count of sequences\n",
"len(random_walks)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###### Dengan panjang path yang kami atur dengan nilai 10, maka didapatkan 40.625 urutan random walk. Urutan ini dapat digunakan sebagai input ke model skip-gram dan mengekstraksi bobot yang dipelajari oleh model (node embedding)."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"from gensim.models import Word2Vec\n",
"\n",
"import warnings\n",
"warnings.filterwarnings('ignore')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###### Lalu kami melatih model skip-gram dengan random walk."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(1778978, 2439200)"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# train skip-gram (word2vec) model\n",
"model = Word2Vec(window = 4, sg = 1, hs = 0,\n",
" negative = 10, # for negative sampling\n",
" alpha=0.03, min_alpha=0.0007,\n",
" seed = 14)\n",
"\n",
"model.build_vocab(random_walks, progress_per=2)\n",
"\n",
"model.train(random_walks, total_examples = model.corpus_count, epochs=20, report_delay=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###### Setiap node dalam graph diwakili oleh vektor dengan panjang tetap (100). Sebagai contoh kita cari paling mirip dengan: \"Formal Shirts\"."
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[('peter england men grey solid slim fit formal shirt', 0.8732825517654419),\n",
" ('peter england men orang slim fit solid formal shirt', 0.8653634786605835),\n",
" ('arrow new york men blue white slim fit check formal shirt',\n",
" 0.864309549331665),\n",
" ('van heusen men creamcolour regular fit solid formal shirt',\n",
" 0.8582490682601929),\n",
" ('van heusen men brown purpl slim fit selfdesign formal shirt',\n",
" 0.8579122424125671),\n",
" ('invictu men blue slim fit print formal shirt', 0.8563601970672607),\n",
" ('red tape men black regular fit solid formal shirt', 0.8562281131744385),\n",
" ('rg design men blue slim fit stripe linen formal shirt', 0.8559995293617249),\n",
" ('van heusen men lavend slim fit check formal shirt', 0.8549967408180237),\n",
" ('jainish men orang classic slim fit solid formal shirt', 0.8544467091560364)]"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.similar_by_word('Formal Shirts')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###### Contoh kita cari paling mirip dengan: \"Accesories\""
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[('classic cl icon tape black cap', 0.8467520475387573),\n",
" ('tossido grey check pattern tie', 0.8429974317550659),\n",
" ('tommi hilfig men brown solid belt', 0.8407713174819946),\n",
" ('tommi hilfig men navi blue brown revers solid leather belt',\n",
" 0.8403265476226807),\n",
" ('lino perro black solid broad tie', 0.8362069129943848),\n",
" ('loui philipp men navi blue brown solid revers leather belt',\n",
" 0.8343643546104431),\n",
" ('hrx hrithik roshan unisex charcoal grey print beani', 0.8334780931472778),\n",
" ('knotyy black solid unisex beani', 0.8293745517730713),\n",
" ('invictu blue coffe brown check tie', 0.8290094137191772),\n",
" ('scharf men brown solid leather belt', 0.8253196477890015)]"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.similar_by_word('Accesories')"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
"terms = ['Formal Shirts', 'Accesories', \n",
" 'Casual Shirts','Men Casual Trousers', 'Men Formal Trousers', \n",
" 'Men Jackets Coats','Men Swimwear', 'Men Suits']"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [],
"source": [
"def plot_nodes(word_list):\n",
" X = model[word_list]\n",
" \n",
" # reduce dimensions to 2\n",
" pca = PCA(n_components=2)\n",
" result = pca.fit_transform(X)\n",
" \n",
" \n",
" plt.figure(figsize=(12,9))\n",
" # create a scatter plot of the projection\n",
" plt.scatter(result[:, 0], result[:, 1])\n",
" for i, word in enumerate(word_list):\n",
" plt.annotate(word, xy=(result[i, 0], result[i, 1]))\n",
" \n",
" plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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AMARMQ0AAAA4IqYBAAAAR8Q0AAAA4IiYBgAAABwR0wAAAICjKse0Maa+MSbNGLPNGLPFGPOEPxYGAAAAXO6q+WGMMkn/Y63dYIy5VlKmMWaZtXarH8YGAAAALltVvjNtrT1grd3w/e8LJW2TFF7VcQEAAIDLnV/3TBtjIiTFSVrrz3EBAACAy5HfYtoYU0PSu5JGWWu/q+T9h4wxGcaYjPz8fH9NCwAAAFwyfolpY0yQToT0bGvt/MrOsda+bq2Nt9bG16lTxx/TAgAAAJeUP57mYST9TdI2a+0fq74kAAAA4MrgjzvTbSUNk9TFGJP1/a9efhgXAAAAuKxV+dF41trVkowf1gIAAABcUfgJiAAAAIAjYhoAAABwREwDAAAAjohpAAAAwBExDQAAADgipgEAAABHxDQAAADgiJgGAAAAHBHTAAAAgCNiGgAAAHBETAMAAACOiGkAAADAETENAAAAOCKmAQAAAEfENAAAAOCImAYAAAAcEdPAFeb//b//p8GDB+snP/mJoqKi1KtXL+3YseOCz5uenq4+ffqcdvzo0aO65557FB0dLY/Ho3bt2qmoqEi5ubnyeDyVjjVhwgQtX7680veSk5O1f/9+v64dAIALpdqlXgCAc2et1Z133qn7779fc+bMkSRlZWXp4MGDatq06SVZ05/+9CfdfPPNys7OliRt375dQUFBZ71m4sSJlR4vLy9XcnKyPB6P6tWr5/e1AgDgb9yZBq4gaWlpCgoK0iOPPOI75vV61b59exUVFalr165q0aKFoqOjtWjRIknSkSNH1Lt3b8XGxsrj8Wju3LmSpIiICH399deSpIyMDHXq1EmStG7dOv30pz9VXFycfvrTn2r79u1nXdOBAwcUHh7uex0ZGang4GBJJ+L4F7/4hZo3b67u3buruLhYkpSUlKR58+b51jFx4kS1a9dOKSkpysjI0D333COv16vi4mKNHTtWUVFRiomJ0ejRo/3wKQIA4D/cmQauIDk5OWrZsmWl74WEhGjBggW67rrr9PXXX6tNmzbq16+fPvjgA9WrV0+pqamSpMOHD591jmbNmmnlypWqVq2ali9frmeffVbvvvvuGc8fPny4unfvrnnz5qlr1666//771aRJE0nSzp07lZKSojfeeEN33XWX3n33Xd17772Vrn316tWSpBkzZmjq1KmKj4/XN998owUL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6xjWWj377LOKiYlRt27dlJeXp4MHD57fB/C9n/zkJ0pISJAkrV27Vl26dNGNN96ooKAgDR06VCtXrjzr9W3bttV9992nGTNm6Pjx45JOfH6zZs2S1+tV69atVVBQoJ07d0qSbr/9djVo0EDSiT+DDz74QGPHjtWaNWtUs2ZNp68BAAB/48408B8WbszTlA+3a39BsYpLy7VwY5769eun0aNHKz09XYcOHfKda63Vu+++q8jIyApjrF271rd1Q5ICAwNVVlZW4Zxbb71Ve/fuVWFhoa699toK7+3evVtTp07V+vXrdf311yspKUklJSWqVq2a1q1bp48++khz5szRX/7yF61YsULVqlXzBaq11vcNg7Nnz1Z+fr4yMzMVFBSkiIgIlZSUOH0uYWFhFb7uygQEBFR479S53njjDa1du1aLFy9WbGysNm/eLGutXnnlFXXt2rXCOMuXL68w32233aaMjAwtWbJEY8aMUZ8+fXxbSwAAuJS4Mw2cYuHGPI2bn628gmJZSdZK4+Znq16rnpowYYKio6MrnJ+YmKjp06f7AnLjxo3nPFf16tX185//XI8//rgvfk/uRf7uu+8UFhammjVr6uDBg77tDUVFRTp8+LB69eqll156yfcNgxEREcrMzJQkLVq0SKWlpZJObIe46aabFBQUpLS0tPO+O34mbdq0UVpamg4dOqSysjLNmTNHHTt2VEBAgK6//nrt3LlTx48f14IFC3zXfPnll2rTpo1eeOEFXX/99crLy1NiYqJeeeUV379obN++XcXFxafNl5eXpxo1amjYsGF66qmntGHDBr98HQAAVBV3poFTTPlwu4pLyyscKy4t16ysQq0Z+8Rp548fP16jRo1STEyMrLWKiIjQ4sWLz3m+3/72t/rVr36lqKgohYSEKCwsTBMnTlRsbKzi4uLUvHlzNW7cWG3btpUkFRYW6o477lBJSYmstZo2bZok6Re/+IXuuOMOtWrVSl27dvXd1b3nnnvUt29fxcfHy+v1qlmzZq4fTQW33HKLJk6cqE6dOslaq759+6p3796SpN///vfq0aOHGjRooKioKB07dkyS9OSTT2r37t2y1qp79+7yeDy67bbbtHfvXnm9XknSTTfdVOk3SW7atEljx45VQECArrnmGr366qt++ToAAKgqc6a/rr2Q4uPjbUZGxkWfF/ghjcamqrL/RRhJuyf3vtjLAQAAVWSMybTWxl+o8dnmAZyiXq3Q8zoOAACubsQ0cIoxiZEKDQqscCw0KFBjEiPPcAUAALiasWcaOEX/uBM/3fDk0zzq1QrVmMRI33EAAIBTEdPAf+gfF048AwCAc8I2DwAAAMARMQ0AAAA4IqYBAAAAR8Q0AAAA4IiYBgAAABwR0wAAAIAjYhqAjzFGw4YN870uKytTnTp11KdPH7+M36lTJ2VkZJz3dcnJyRoxYsQ5n5+enq5PPvnkvObYsWOHevXqpVtvvVW33Xab7rrrLh08ePB8l6rc3Fz9/e9/P+/rAABXJmIagE9YWJhycnJUXFwsSVq2bJnCw6+8Z26fb0yXlJSod+/eevTRR7Vr1y5t27ZNjz76qPLz8897bmIaAK4uxDSACnr27KnU1FRJUkpKioYMGeJ778iRIxo+fLgSEhIUFxenRYsWSTpx53jAgAHq0aOHmjRpoqeffvoH53n00UcVHx+v5s2b6/nnn/cdX79+vX76058qNjZWrVq1UmFhYYXrUlNTdfvtt+vrr79Wfn6+Bg4cqISEBCUkJGjNmjXKzc3Vq6++qmnTpsnr9WrVqlX6xz/+IY/Ho9jYWHXo0OG0tfz973/X7bffrr59+/qOde7cWR6PRyUlJXrggQcUHR2tuLg4paWlSToRze3bt1eLFi3UokULX7yPHTtWq1atktfr1bRp07Rlyxa1atVKXq9XMTEx2rlz57n+UQAArgTW2ov+q2XLlhbA5ScsLMxu2rTJDhw40BYXF9vY2FiblpZme/fuba21dty4cfatt96y1lr77bff2iZNmtiioiI7a9Ys26hRI1tQUGCLi4ttgwYN7N69e08bv2PHjnb9+vXWWmsPHTpkrbW2rKzMduzY0W7atMkeO3bMNmrUyK5bt85aa+3hw4dtaWmpnTVrlv3lL39p58+fb9u1a2e/+eYba621Q4YMsatWrbLWWrtnzx7brFkza621zz//vJ0yZYpvXo/HY7/66ivfuv/Tk08+aV966aVKP5OpU6fapKQka62127Zts/Xr17fFxcX2yJEjtri42Fpr7Y4dO+zJf66d+nlZa+2IESPs22+/ba219tixY/bo0aNn+yMAAPiZpAx7AbuWHycOXOUWbszTlA+3a39BsYpLy/Vl+Q3Kzc1VSkqKevXqVeHcpUuX6r333tPUqVMlndgesXfvXklS165dVbNmTUlSVFSU9uzZo/r1659x3nfeeUevv/66ysrKdODAAW3dulXGGNWtW1cJCQmSpOuuu853flpamjIyMrR06VLf8eXLl2vr1q2+c7777rvT7mRLUtu2bZWUlKS77rpLAwYMOK/PZ/Xq1Ro5cqQkqVmzZmrYsKF27Nihhg0basSIEcrKylJgYKB27NhR6fW33367Jk2apK+++koDBgxQkyZNzmt+AMDlrUoxbYyZIqmvpH9L+kLSA9baAn8sDMCFt3BjnsbNz1ZxabkkyVpp3PxseRM6afTo0UpPT9ehQ4d851tr9e677yoyMrLCOGvXrlVwcLDvdWBgoMrKys447+7duzV16lStX79e119/vZKSklRSUiJrrYwxlV7TuHFjffnll9qxY4fi4+MlScePH9enn36q0NDQs36dr776qtauXavU1FR5vV5lZWXphhtu8L3fvHlzffzxx5Vee+KmxummTZumm2++WZs2bdLx48cVEhJS6XlDhw5V69atlZqaqsTERM2YMUNdunQ563oBAFeOqu6ZXibJY62NkbRD0riqLwnAxTLlw+2+kD6puLRcO2slaMKECYqOjq7wXmJioqZPn+4LzI0bNzrN+9133yksLEw1a9bUwYMH9f7770s6ced3//79Wr9+vSSpsLDQF+UNGzbU/Pnzdd9992nLli2SpO7du+svf/mLb9ysrCxJ0rXXXlvhDvUXX3yh1q1ba+LEibrxxhu1b9++CusZOnSoPvnkE99ecUn64IMPlJ2drQ4dOmj27NmSTjzxY+/evYqMjNThw4dVt25dBQQE6K233lJ5eXmlc3/55Zdq3LixHn/8cfXr10+bN292+swAAJenKsW0tXaptfbk7afPJN1S9SUBuFj2FxRXevyQraEnnnjitOPjx49XaWmpYmJi5PF4NH78+POar6ysTMHBwYqNjVVcXJyaN2+u4cOHq23btpKka665RnPnztXIkSMVGxurn/3sZyopKfFdHxkZqdmzZ2vQoEH64osv9Oc//1kZGRmKiYlRVFSUXn31VUlS3759tWDBAt83II4ZM0bR0dHyeDzq0KGDYmNjK6wrNDRUixcv1vTp09WkSRNFRUUpOTlZN910kx577DGVl5crOjpad999t5KTkxUcHKzHHntMb775ptq0aaMdO3YoLCxMkhQTE6Nq1aopNjZW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\n",
"text/plain": [
"<Figure size 864x648 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plot_nodes(terms)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"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.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment