{"id":85712,"date":"2021-12-23T09:00:38","date_gmt":"2021-12-23T03:30:38","guid":{"rendered":"https:\/\/techvidvan.com\/tutorials\/?p=85712"},"modified":"2021-12-23T09:00:38","modified_gmt":"2021-12-23T03:30:38","slug":"twitter-hashtag-prediction-machine-learning","status":"publish","type":"post","link":"https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/","title":{"rendered":"Twitter Hashtag Prediction Project using Machine learning"},"content":{"rendered":"<p>In this project, we will create a Machine Learning model that will analyze tweets about the weather forecast and then predict all of the hashtags associated with those tweets. The model will take tweets as input and separate each word of those tweets into three groups, namely &#8220;Sentiments&#8221;, &#8220;When,&#8221; and &#8220;Kind.&#8221;<\/p>\n<p>The \u201cSentiment\u201d category describes how people feel about the weather, whether they are happy, sad, or neutral. Weather timing is described in the \u201cWhen\u201d category, which includes the past, present, and future. The weather conditions like \u2018stormy\u2019, \u2018thunder\u2019, \u2018lightning\u2019 are described in the \u201cKind\u201d category.<\/p>\n<p>For example, if someone tweets \u201cYesterday&#8217;s stormy weather was extremely frightening.\u201d So for \u201cSentiments\u201d, we will say \u201chow does the person feel about the weather?\u201d So the answer is \u201cextremely frightening\u201d, for \u201cWhen\u201d we will say \u201cwhen did it happen?\u201d the answer is \u201cYesterday\u201d now for \u201cKind\u201d we will say \u201cwhat kind of weather was there?\u201d so the answer is \u201cstormy\u201d. We can choose only one value from the \u201cSentiment\u201d and \u201cWhen\u201d categories but are allowed multiple choices for the \u201ckind\u201d.<\/p>\n<p>For this, we are going to use the Many to Many Encoder-Decoder Sequence Model.<\/p>\n<p>This Sequence model accepts a stream of sentences as input and outputs another stream of sentences. The two main techniques used in sequence modeling are encoder and decoder along with the neural network Layer. We will be using the LSTM neural network along with Encoder and Decoder.<\/p>\n<p>The encoder model takes the input sequence of tweets and passes it to 3 stacked Layers of the LSTM network which after processing returns the hidden state(output of the previous layer) or cell states (stored value) and passes to the next layers. The final output from the encoder model is the input for the Decoder model which will then predict the output sequence using one LSTM layer and Attention mechanism. The attention mechanism helps the model to focus only on specific words for the prediction.<\/p>\n<p>There are two classes of Attention Mechanism.<\/p>\n<p>a) Global Attention :<br \/>\nb) Local Attention<\/p>\n<p><strong>Global Attention<\/strong>: In Global attention, all the hidden states of LSTM layers at different time steps are used to generate the context vector.<\/p>\n<p><strong>Local Attention<\/strong>: In Local attention, some of the hidden states of the LSTM layers are used to generate the context vector.<\/p>\n<h3>Encoder-Decoder model:<\/h3>\n<p><a href=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/encoder-decoder-architecture.webp\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-85715\" src=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/encoder-decoder-architecture.webp\" alt=\"encoder decoder architecture\" width=\"945\" height=\"597\" \/><\/a><\/p>\n<h3>Prerequisites :<\/h3>\n<p>You must be familiar with Python, Deep Learning, and Natural Language Processing(NLP). Using the following command, you can install all of the project&#8217;s modules:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">pip install numpy, pandas, pickle, nltk, tensorflow, sklearn<\/pre>\n<p>The versions of Python and its relevant modules used in this project are as follows:<\/p>\n<ol>\n<li>python : 3.8.5<\/li>\n<li>tensorflow : 2.3.1 <em><strong>Note<\/strong>: TensorFlow version should be 2.2 or higher in order to use keras or else install keras directly<\/em><\/li>\n<li>sklearn : 0.24.2<\/li>\n<li>pickle : 4.0<\/li>\n<li>numpy : 1.19.5<\/li>\n<li>pandas : 1.1.5<\/li>\n<li>nltk : 3.2.5<\/li>\n<\/ol>\n<h3>Datasets for Twitter Hashtag Prediction Project:<\/h3>\n<p>You can download the datasets for Twitter Hashtag prediction project from the following link: <a href=\"https:\/\/www.kaggle.com\/c\/crowdflower-weather-twitter\/data\"><strong>Twitter Hashtag prediction Dataset<\/strong><\/a><\/p>\n<h3>Download Twitter Hashtag Prediction Project Code<\/h3>\n<p>Please download the source code of twitter hashtag prediction project with machine learning: <a href=\"https:\/\/drive.google.com\/file\/d\/1HMb5I9P7Mh9Y24Cl-mQ8o3XIremD2ncf\/view?usp=sharing\"><strong>Twitter Hashtag Prediction Project Code<\/strong><\/a><\/p>\n<h3>Project Structure :<\/h3>\n<p><strong>train.csv<\/strong>: This file contains training data for our model. It has tweets, locations, and a confidence score for each of 24 possible labels. These 24 labels are from three categories: sentiment, when and kind.<\/p>\n<p><strong>test.csv<\/strong>: This file contains testing data for our model. It has tweets and locations.<\/p>\n<p><strong>twitter_hashtag.py<\/strong>: In this file, we will create and train our model with input and target to predict the hashtag for the tweet.<\/p>\n<p><strong>s2s\/<\/strong>: Our trained model&#8217;s optimizer, metrics, and weights are all stored in this directory.<\/p>\n<p><strong>contractions.pkl<\/strong>: This file provides a dictionary with keys representing abbreviated words and values representing their extended or original meanings.<\/p>\n<h3>Steps for Twitter Hashtag Prediction ML Project:<\/h3>\n<h4>1) Import the Libraries<\/h4>\n<p>Firstly we will create a file called \u2018twitter_hashtag.py\u2019 and import all the libraries which have been shared in the prerequisites section.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#TechVidvan Twitter Hashtag Prediction Project\n#import all the required libraries\nimport numpy as np\nimport pandas as pd\nimport pickle\nfrom statistics import mode\nimport nltk\nfrom nltk import word_tokenize\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras import models\nfrom tensorflow.keras.preprocessing.sequence import pad_sequences\nfrom tensorflow.keras.preprocessing.text import Tokenizer\nfrom tensorflow.keras.utils import plot_model\nfrom tensorflow.keras.layers import Input,LSTM,Embedding,Dense,Concatenate,Attention\nfrom sklearn.model_selection import train_test_split\nnltk.download('wordnet')\nnltk.download('punkt')<\/pre>\n<h4>2) Parse the Dataset file.<\/h4>\n<p>We will traverse the dataset folder which contains the \u2018train.csv\u2019 file and extract all the input texts. Our input will be the \u2018tweet\u2019 column which contains users&#8217; tweets and the target label will be <strong>s1,s2,s3,s4,s5<\/strong> i.e \u201csentiment\u201d, <strong>w1,w2,w3,w4<\/strong> i.e \u201cwhen\u201d and<strong> k1,k2,k3&#8230;.k15<\/strong> i.e \u201ckind\u201d column. The target label value will be the hashtag value of respective labels from s1 to k15.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#read the dataset file\ntrain=pd.read_csv(\"train.csv\")\n\n#tweet column is input\ninp_data=train[\"tweet\"]\n#target data is sentiment(s1,s2,s3,s4,s5) ,\n#when (w1,w2,w3,w4) and kind(k1,k2,k3...k15)\ntar_data=train.iloc[:,4:].values\n\n#get the column name of target\ntar_lab=train.iloc[:,4:].columns.tolist()\n\n#value of the target label like\n#s1=\"I can't tell\" , s2=\"Negative\" and so on till s5\n#w1=\"current weather\", w2=future forecast and so on till w4\n#k1=\"clouds\", k2=\"cold\", k3=\"dry\" and so on till k15\ntar_lab_val=[\n\"I can't tell\",\"Negative\",\"Neutral\",\"Positive\",\"Tweet not related to weather condition\",\n\"current (same day) weather\",\"future (forecast)\",\"I can't tell\",\"past weather\",\n\"clouds\",\"cold\",\"dry\",\"hot\",\"humid\",\"hurricane\",\"I can't tell\",\"ice\",\"other\",\"rain\",\n\"snow\",\"storms\",\"sun\",\"tornado\",\"wind\"]<\/pre>\n<p><strong>Input Data from \u2018train.csv\u2019<\/strong><\/p>\n<p><a href=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/hash-tag-input-data.webp\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-85723\" src=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/hash-tag-input-data.webp\" alt=\"input data\" width=\"963\" height=\"413\" \/><\/a><\/p>\n<p><strong>Target Data from \u2018train.csv\u2019:<\/strong><\/p>\n<p><a href=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/target-data.webp\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-85724\" src=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/target-data.webp\" alt=\"target data\" width=\"1068\" height=\"463\" \/><\/a><\/p>\n<p><strong>Label Value:<\/strong><\/p>\n<p><a href=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/hash-tag-label-value.webp\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-85725\" src=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/hash-tag-label-value.webp\" alt=\"hash tag label value\" width=\"485\" height=\"501\" \/><\/a><\/p>\n<h4>3) Preprocessing<\/h4>\n<p>We need to clean our tweet texts as this data might be incomplete and it cannot be sent directly to the model. So we will create a function \u2018clean()\u2019 which does the following process in order to clean the data and returns the cleaned words:<br \/>\na) Remove numbers, Alphanumeric words i.e. words which contain both alphabets and integers e.g. hello123 .<br \/>\nb) Expand the contraction words which are combinations of two words, shortened using apostrophe for example \u2018aren\u2019t\u2019 shortened for \u2018are not\u2019.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#clean the tweets\ndef clean(tweet):\n #replace and lower case the tweets\n tweet=tweet.replace(\":\",\"\").lower()\n #get only words that contains alphabets\n words= list(filter(lambda w:(w.isalpha()),tweet.split(\" \")))\n #expand the shortened words\n words= [contractions[w] if w in contractions else w for w in words ]\n #return all the words\n return words<\/pre>\n<p>Now we will pass our input data that is training tweets to the \u2018clean()\u2019 function to get clean words and tweets.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#iterate over input data\nfor tweet in inp_data:\n #clean the tweets\n inpt_words= clean(tweet)\n #store the input texts and words\n inp_texts+= [' '.join(inpt_words)]\n inp_words+= inpt_words<\/pre>\n<p>As we are using many to many encoder-decoder sequence models, we need to make our target data also ready for the model. We will convert our confidence scores of \u201csentiments\u201d, \u201cwhen\u201d and \u201ckind\u201d data back in the form of labels. As we can take only one value from \u201csentiments\u201d and \u201cwhen\u201d labels, so for that we will take the maximum confidence score. And for the \u201ckind\u201d type we can have as many but we will take values that have a confidence score greater than 0.5.<\/p>\n<p>We also need to have a starting and ending point for the target data as this will tell the model that from the starting word the sentence begins and after reaching the ending word the sentence ends. For example, we will take the following sentence <strong>\u201cTechVidvan provides many projects\u201d<\/strong> and now we will add <strong>\u201csos\u201d (start of a sentence) at the starting of this sentence and \u201ceos\u201d<\/strong> (end of the sentence) at the end of that sentence. So our new sentence will be \u201csos TechVidvan provides many projects eos\u201d. Let\u2019s see how it works:<\/p>\n<p><strong>Input(x)\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0Output(y)<\/strong><br \/>\n<strong>sos<\/strong>,\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 TechVidvan<br \/>\nsos TechVidvan,\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 provides<br \/>\nsos TechVidvan provides,\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0many<br \/>\nsos TechVidvan provides many,\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 projects<br \/>\nsos TechVidvan provides many projects,\u00a0 \u00a0 \u00a0 <strong>eos<\/strong><\/p>\n<p>As you can see after feeding the input(x) word we get output(y) which is the next word. After reaching \u201ceos\u201d we will stop as it indicates the end of the sentence.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#iterate over target data\nfor lab in tar_data:\n #get index of maximum value from sentiment data(s1 to s5)\n #with the help of this index get label value\n senti=tar_lab[np.argmax(lab[:5])]\n\n #get index of maximum value from when data(w1 to w4)\n #with the help of this index get label value\n when=tar_lab[np.argmax(lab[5:9])+5]\n\n #get index of values greater than 0.5 and get label value from it\n kind=[tar_lab[ind] for ind,ele in enumerate(lab[9:len(lab)],9) if ele&gt;=0.5]\n\n #store the target text which is combination of sentiment,when and kind data\n #add sos at start and eos at end of text\n tar_texts+=[\"sos \"+\" \".join([senti]+[when]+kind)+\" eos\"]<\/pre>\n<p>Now let&#8217;s see how many unique words are in input and target data along with the maximum input and target length.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#only store unique words from the input and target word lists\ninp_words = sorted(list(set(inp_words)))\nnum_inp_words = len(inp_words)\nnum_tar_words = len(tar_lab)+2\n\n#get the length of the input and the target texts which appears most frequently\nmax_inp_len = mode([len(i) for i in inp_texts])\nmax_tar_len = mode([len(i) for i in tar_texts])\n\nprint(\"number of input words : \",num_inp_words)\nprint(\"number of target words : \",num_tar_words)\nprint(\"maximum input length : \",max_inp_len)\nprint(\"maximum target length : \",max_tar_len)<\/pre>\n<p><strong>Output:<\/strong><\/p>\n<p><a href=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/words-and-length.webp\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-85726\" src=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/words-and-length.webp\" alt=\"words and length\" width=\"489\" height=\"138\" \/><\/a><\/p>\n<h4>4) Training and Testing sets<\/h4>\n<p>We will split the input and target texts into a 90:10 ratio. 90% for the training set and 10% for the testing set.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#split the input and target text into 90:10 ratio or testing size of 10%=0.1.\nx_train,x_test,y_train,y_test=train_test_split(input_texts,target_texts,test_size=0.1,random_state=42)<\/pre>\n<h4>5) Text Vectorization<\/h4>\n<p>As our model requires numeric data, we will use text vectorization. Text Vectorization is a technique that converts textual data into numeric data. Numeric data can be the index of respective textual data.<\/p>\n<p>For example,<br \/>\n<strong>L = [ \u2018on monday\u2019, \u2018free product\u2019, \u2018you are best\u2019]<\/strong><br \/>\nTokenize all the elements of list \u2018L\u2019 and make a dictionary having keys as tokens and value as their index+1. So after the data is fit we get a dictionary as<\/p>\n<p><strong>D={ \u2018on\u2019:1, \u2018monday\u2019:2, \u2018free\u2019:3, \u2018product\u2019:4, \u2018you\u2019:5, \u2018are\u2019:6, \u2018best\u2019:7 }<\/strong><br \/>\nSo we have fit our data, now let\u2019s transform the below sentence into an integer sequence using our tokenizer.<\/p>\n<p><strong>S = \u201care you free on monday\u201d<\/strong><\/p>\n<p><strong>Transformed (Vectorized) S : [ 6 , 5 , 3 , 1 , 2 ]<\/strong><br \/>\nSo we will convert our input and target text into a sequence of integers using a vectorization technique.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#Use all of the words from training input and output to train the tokenizer.\ninp_tokenizer = Tokenizer()\ninp_tokenizer.fit_on_texts(x_train)\ntar_tokenizer = Tokenizer()\ntar_tokenizer.fit_on_texts(y_train)\n\n#convert text to an integer sequence where the integer represents the word index\nx_train= inp_tokenizer.texts_to_sequences(x_train)\ny_train= tar_tokenizer.texts_to_sequences(y_train)<\/pre>\n<p>We&#8217;ll make all of the input and target texts the same length after converting them to integer sequences for our model. We will pad an array of 0&#8217;s to the integer sequence if it is smaller than the provided maximum input length using the &#8216;max in len&#8217; and &#8216;max tr len&#8217; variables.<\/p>\n<p>We&#8217;ll pad our encoder input data (&#8216;x train&#8217;) and our decoder input data (&#8216;y train&#8217;) but we won&#8217;t include the last word, &#8216;eos.&#8217; The decoder target data will be the same as the decoder input data, but it will be one timestep ahead since it will not include our target sentence&#8217;s first word,&#8217;sos.&#8217;<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#If the length is less than the maximum length, pad the array with 0s.\nenc_inp_data= pad_sequences(x_train, maxlen=max_inp_len, padding='post',dtype=\"float32\")\ndec_data= pad_sequences(y_train, maxlen=max_tar_len, padding='post',dtype=\"float32\")\n\n#The last word, ie 'eos,' will not be included in the decoder input data.\ndec_inp_data = dec_data[:,:-1]\n\n#decoder target data will be one time step ahead as it will not include the first initial word i.e 'sos'\ndec_tar_data = dec_data.reshape(len(dec_data),max_tar_len,1)[:,1:]<\/pre>\n<h4>6) Build the model.<\/h4>\n<p>The LSTM network will have three stacked layers. This will greatly improve our prediction. As per your requirement, you can have more also. Let&#8217;s have a look at our encoder and decoder models.<\/p>\n<p><strong><span style=\"text-decoration: underline\">Encoder<\/span>:<\/strong> The &#8216;Input&#8217; object will be used to initialize the encoder input tensor. The batch is expected to have 14 (maximum input length) dimensions. Then we&#8217;ll make a &#8216;Embedding Layer,&#8217; with the total number of input words as the first argument and a shape of 500 for the latent (hidden) dimension.<\/p>\n<p><strong><span style=\"text-decoration: underline\">LSTM<\/span>:<\/strong> The input of the encoder will be used in the first LSTM layer, and so on, creating a continuous succession of LSTM layers. All of the contextual information in the input sequence will be captured by the LSTM layer. Following the execution of each LSTM layer, we will deliver hidden state output as well as states (hidden state and cell state).<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">from keras import backend as K\nK.clear_session()\nlatent_dim = 500\n\n#create input object with the shape equal to the maximum number of input words\nenc_inputs = Input(shape=(max_inp_len,))\nenc_embedding = Embedding(num_inp_words+1, latent_dim)(enc_inputs)\n\n\n#create 3 stacked LSTM layer\n#1st LSTM layer keep only output\nenc_lstm1= LSTM(latent_dim, return_state=True, return_sequences=True)\nenc_outputs1, *_ = enc_lstm1(enc_embedding)\n\n#2nd LSTM layer keep only output\nenc_lstm2= LSTM(latent_dim, return_state=True, return_sequences=True)\nenc_outputs2, *_ = enc_lstm2(enc_outputs1)\n\n#3rd LSTM layer keep output as well as its states\nenc_lstm3= LSTM(latent_dim,return_sequences=True,return_state=True)\nenc_outputs3 , state_h3 , state_c3= enc_lstm3(enc_outputs2)\n\n#encoder states\nenc_states= [state_h3, state_c3]<\/pre>\n<p><strong><span style=\"text-decoration: underline\">Decoder<\/span>:<\/strong> We&#8217;ll build the decoder input tensor similarly to Encoder and then give it to the single LSTM. The initial state of the decoder is where we will pass the hidden state and cell state values that we obtained from the encoder&#8217;s LSTM layer.<\/p>\n<p><strong><span style=\"text-decoration: underline\">Attention Layer<\/span>:<\/strong> The encoder and decoder outputs will be passed to the attention layer, which will then concatenate the attention layer outputs with the decoder outputs.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\"># Decoder.\ndec_inputs = Input(shape=(None,))\ndec_emb_layer = Embedding(num_tar_words+1, latent_dim)\ndec_embedding = dec_emb_layer(dec_inputs)\n\n#initialize the LSTM layer of the decoder with the encoder's output states\ndec_lstm = LSTM(latent_dim, return_sequences=True, return_state=True)\ndec_outputs, *_ = dec_lstm(dec_embedding,initial_state=enc_states)\n\n#Attention layer\nattention =Attention()\nattn_out = attention([dec_outputs,enc_outputs3])\n\n#Merge the attention output with the decoder outputs\nmerge=Concatenate(axis=-1, name='concat_layer1')([dec_outputs,attn_out])<\/pre>\n<p>We&#8217;ll now build our Dense Layer, which will be the model&#8217;s output layer. It will have the output dimension the same as a number of target word units of output dimension along with the softmax activation function.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#fully connected Dense layer for the output\ndec_dense = Dense(num_tar_words+1, activation='softmax')\ndec_outputs = dec_dense(merge)<\/pre>\n<h4>7) Train the model.<\/h4>\n<p>Finally, we&#8217;ll set up encoder and decoder inputs, as well as decoder output, in our Model class. We&#8217;ll plot the model layers and get a summary of our model.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#Model class and model summary\nmodel = Model([enc_inputs, dec_inputs], dec_outputs)\nmodel.summary()\nplot_model(model, to_file='model_plot.png', show_shapes=True, show_layer_names=True)<\/pre>\n<p><strong>Output:<\/strong><\/p>\n<p><a href=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/twitter-hash-tag-model-summary.webp\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-85727\" src=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/twitter-hash-tag-model-summary.webp\" alt=\"twitter hash tag model summary\" width=\"857\" height=\"537\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/model-plot.webp\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-85728\" src=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/model-plot.webp\" alt=\"model plot\" width=\"1088\" height=\"959\" \/><\/a><\/p>\n<p>Now we will train our model by passing the encoder input data, decoder input data as input for the model and decoder target data as output with \u2018500\u2019 batch size, for \u201810\u2019 epochs and the optimizer will be \u2018RMSprop\u2019. You can increase or decrease the epoch but take care of the validation accuracy and loss.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#compile the model using RMSProp optimizer\nmodel.compile(\n optimizer=\"rmsprop\", loss=\"sparse_categorical_crossentropy\", metrics=[\"accuracy\"])\n\n#train the model with input and target data from encoder and decoder\nmodel.fit(\n [enc_inp_data, dec_inp_data],dec_tar_data,\nbatch_size=500,epochs=10)\n\n#Save model with the name as \u201cs2s\u201d\nmodel.save(\"s2s\")<\/pre>\n<p><strong>Output:<\/strong><\/p>\n<p><a href=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/ml-model-train.webp\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-85729\" src=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/ml-model-train.webp\" alt=\"ml model train\" width=\"1048\" height=\"451\" \/><\/a><\/p>\n<p>After training the model, we got an accuracy of 95.49%.<\/p>\n<h4>8) Inference Model<\/h4>\n<p>We will be using the trained model to create an inference architecture for the encoder and decoder model. Load the model. By using the Inference model we will test our model on new sentences for which the target sequence is unknown.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\"># encoder inference model\nlatent_dim=500\n\n#load the saved model\nmodel = models.load_model(\"s2s\")<\/pre>\n<p><span style=\"text-decoration: underline\"><strong>Encoder Inference:<\/strong> <\/span>The 0th layer, i.e. the input object that we constructed (as seen in the above summary and model plot), will be the input for the inference encoder model, and the output will be the output of the last LSTM, which is the 6th layer.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#construct an encoder model from the output of the 6th layer of LSTM\nenc_outputs,state_h_enc,state_c_enc = model.layers[6].output\nenc_states=[state_h_enc,state_c_enc]\n\n#add input data and state data from the layer\nenc_model = Model(model.input[0],[enc_outputs]+enc_states)<\/pre>\n<p><span style=\"text-decoration: underline\"><strong>Decoder Inference:<\/strong><\/span> We&#8217;ll get the input, embedding, and LSTM layers from the stored model, just as the Encoder inference model. The shape of latent (hidden) dimensions should be used to initialize the decoder hidden input and the other two states.<\/p>\n<p><span style=\"text-decoration: underline\"><strong>Attention Inference:<\/strong> <\/span>The attention layer is the eighth layer in our case. We&#8217;ll get it and combine the output of the inference decoder with the hidden state input we set up earlier. The attention layer output will then be concatenated with the decoder output.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\"># decoder inference model\n#create Input object of hidden state and cell state for decoder\ndec_state_input_h = Input(shape=(latent_dim,))\ndec_state_input_c = Input(shape=(latent_dim,))\ndec_hidden_state_input = Input(shape=(max_inp_len,latent_dim))\n\n#Get all the layers from the model\ndec_inputs = model.input[1]\ndec_emb_layer = model.layers[5]\ndec_lstm = model.layers[7]\ndec_embedding= dec_emb_layer(dec_inputs)\n\n#add input and initialize the LSTM layer with decoder\u2019s hidden and cell state\ndec_outputs2, state_h2, state_c2 = dec_lstm(dec_embedding, initial_state=[dec_state_input_h,dec_state_input_c])\n\n#Attention layer\nattention = model.layers[8]\nattn_out1 = attention([dec_outputs2,dec_hidden_state_input])\nmerge2 = Concatenate(axis=-1)([dec_outputs2, attn_out1])<\/pre>\n<p>And same for the Dense layer (output layer) which is the 10th layer of our saved model. With the help of the above data, initialize the Inference Model class.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#Dense layer for decoder output\ndec_dense = model.layers[10]\ndec_outputs2 = dec_dense(merge2)\n\n# Finally define the Decoder model Class\ndec_model = Model(\n[dec_inputs] + [dec_hidden_state_input,dec_state_input_h,dec_state_input_c],\n[dec_outputs2] + [state_h2, state_c2])<\/pre>\n<p>Assign state vectors to the input sequence. For each pair, create an empty array containing the intended sequence and generate the start word, which in our case is \u2018sos\u2019. Predict the output index using this state value and the input sequence. To obtain the word from the output index, use the reverse target word index and append it to the decoded sequence.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#create a dictionary with all indexes as key and respective target label as values\nreverse_tar_word_index = tar_tokenizer.index_word\nreverse_inp_word_index = inp_tokenizer.index_word\ntar_word_index = tar_tokenizer.word_index\nreverse_tar_word_index[0]=' '\n\ndef decode_sequence(inp_seq):\n #get the encoder outputs and states(hidden and cell) by passing the input\n sequence\n enc_out, enc_h, enc_c= enc_model.predict(inp_seq)\n\n #target sequence with starting initial word as 'sos'\n tar_seq = np.zeros((1, 1))\n tar_seq[0, 0] = tar_word_index['sos']\n\n #Stop the iteration if the iteration reaches end of the text\n stop_condition = False\n #merge every predicted word in decoded sentence\n decoded_sentence = \"\"\n while not stop_condition:\n  #get predicted output words, hidden and cell state for the model\n output_words, dec_h, dec_c= dec_model.predict([tar_seq] + [enc_out,enc_h, enc_c])\n\n #Using index get the word from the dictionary\n word_index = np.argmax(output_words[0, -1, :])\n text_word = reverse_tar_word_index[word_index]\n decoded_sentence += text_word +\" \"<\/pre>\n<p>Assign the index of our word to the target sequence, so that our target sequence has a vector of the previous word for the next iteration. Iterate until our word equals the last word (in our example, &#8216;eos&#8217;) or the target text&#8217;s maximum length.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\"># Stop when we either hit max length or reach the terminal word i.e. eos.\nif text_word == \"eos\" or len(decoded_sentence) &gt; max_tar_len:\n stop_condition = True\n\n\n#update target sequence with the current word index.\ntar_seq = np.zeros((1, 1))\ntar_seq[0, 0] = word_index\nenc_h, enc_c = dec_h, dec_c\n\n\n#return the decoded sentence string\nreturn decoded_sentence<\/pre>\n<p>Finally, we are done with all the processes and now we can predict the Hashtag for the input tweet. For this, we will clean and vectorize our \u2018x_test\u2019 and then pass to the \u2018decode_sequence()\u2019 function to get the predicted hashtag.<\/p>\n<p><strong>Code:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#dict with key as label and value as target label value\nlab_val=dict((i,v) for i,v in zip(tar_lab,tar_lab_val))\n\nfor i in range(0,20,3):\n #tokenize the x_test and convert into integer sequence\n inp_x= inp_tokenizer.texts_to_sequences([x_test[i]])\n #pad array of 0's\n inp_x= pad_sequences(inp_x, maxlen=max_inp_len, padding='post')\n #reshape the input x_test\n tag=decode_sequence(inp_x.reshape(1,max_inp_len)).replace('eos','')\n print(\"Tweet:\",x_test[i])\n print(\"Predicted Hashtag:\",\" \".join([\"#\"+lab_val[i] for i in word_tokenize(tag)]))\n print(\"Actual Hashtag:\",\" \".join([\"#\"+lab_val[i] for i in y_test[i][4:-4].split(\" \")]))\n print(\"\\n\")<\/pre>\n<h3>Twitter Hashtag Prediction Output<\/h3>\n<p><a href=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/twitter-hashtag-prediction-output-1.webp\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-85730\" src=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/twitter-hashtag-prediction-output-1.webp\" alt=\"twitter hashtag prediction output\" width=\"1196\" height=\"503\" \/><\/a><\/p>\n<p><a href=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/twitter-hashtag-prediction-output-2.webp\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-85731\" src=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2021\/12\/twitter-hashtag-prediction-output-2.webp\" alt=\"twitter hashtag prediction output 2\" width=\"1076\" height=\"185\" \/><\/a><\/p>\n<h3>Summary<\/h3>\n<p>In this project, we have developed a Twitter Hashtag prediction model which generates Hashtag from the provided tweet using the LSTM model and Attention Mechanism. We got an accuracy of <strong>95.49%<\/strong>. To improve model accuracy you can change some parameters like training and testing sets or you can go for Bidirectional LSTM also.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this project, we will create a Machine Learning model that will analyze tweets about the weather forecast and then predict all of the hashtags associated with those tweets. The model will take tweets&#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":85732,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[210],"tags":[204,3397,4566,4567,4568],"class_list":["post-85712","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-machine-learning","tag-machine-learning-project","tag-ml-project","tag-twitter-hashtag-prediction","tag-twitter-hashtag-prediction-project","tag-twitter-machine-learning"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Twitter Hashtag Prediction Project using Machine learning - TechVidvan<\/title>\n<meta name=\"description\" content=\"Create Twitter Hashtag Prediction Project using machine learning model. Analyze tweets in real-time and predict their hashtags.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Twitter Hashtag Prediction Project using Machine learning - TechVidvan\" \/>\n<meta property=\"og:description\" content=\"Create Twitter Hashtag Prediction Project using machine learning model. Analyze tweets in real-time and predict their hashtags.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/\" \/>\n<meta property=\"og:site_name\" content=\"TechVidvan\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/TechVidvan\/\" \/>\n<meta property=\"article:published_time\" content=\"2021-12-23T03:30:38+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/2021\/12\/twitter-hashtag-prediction-machine-learning-project.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"628\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"author\" content=\"TechVidvan Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@vidvantech\" \/>\n<meta name=\"twitter:site\" content=\"@vidvantech\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"TechVidvan Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 minutes\" \/>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Twitter Hashtag Prediction Project using Machine learning - TechVidvan","description":"Create Twitter Hashtag Prediction Project using machine learning model. Analyze tweets in real-time and predict their hashtags.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/","og_locale":"en_US","og_type":"article","og_title":"Twitter Hashtag Prediction Project using Machine learning - TechVidvan","og_description":"Create Twitter Hashtag Prediction Project using machine learning model. Analyze tweets in real-time and predict their hashtags.","og_url":"https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/","og_site_name":"TechVidvan","article_publisher":"https:\/\/www.facebook.com\/TechVidvan\/","article_published_time":"2021-12-23T03:30:38+00:00","og_image":[{"width":1200,"height":628,"url":"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/2021\/12\/twitter-hashtag-prediction-machine-learning-project.webp","type":"image\/webp"}],"author":"TechVidvan Team","twitter_card":"summary_large_image","twitter_creator":"@vidvantech","twitter_site":"@vidvantech","twitter_misc":{"Written by":"TechVidvan Team","Est. reading time":"16 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/#article","isPartOf":{"@id":"https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/"},"author":{"name":"TechVidvan Team","@id":"https:\/\/techvidvan.com\/tutorials\/#\/schema\/person\/e9c26e74dd3d87421f7ada9433b8cd22"},"headline":"Twitter Hashtag Prediction Project using Machine learning","datePublished":"2021-12-23T03:30:38+00:00","mainEntityOfPage":{"@id":"https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/"},"wordCount":2159,"commentCount":0,"publisher":{"@id":"https:\/\/techvidvan.com\/tutorials\/#organization"},"image":{"@id":"https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/#primaryimage"},"thumbnailUrl":"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/2021\/12\/twitter-hashtag-prediction-machine-learning-project.webp","keywords":["machine learning project","ML project","Twitter Hashtag Prediction","Twitter Hashtag Prediction Project","twitter machine learning"],"articleSection":["Machine Learning Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/","url":"https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/","name":"Twitter Hashtag Prediction Project using Machine learning - TechVidvan","isPartOf":{"@id":"https:\/\/techvidvan.com\/tutorials\/#website"},"primaryImageOfPage":{"@id":"https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/#primaryimage"},"image":{"@id":"https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/#primaryimage"},"thumbnailUrl":"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/2021\/12\/twitter-hashtag-prediction-machine-learning-project.webp","datePublished":"2021-12-23T03:30:38+00:00","description":"Create Twitter Hashtag Prediction Project using machine learning model. Analyze tweets in real-time and predict their hashtags.","breadcrumb":{"@id":"https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/#primaryimage","url":"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/2021\/12\/twitter-hashtag-prediction-machine-learning-project.webp","contentUrl":"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/2021\/12\/twitter-hashtag-prediction-machine-learning-project.webp","width":1200,"height":628,"caption":"twitter hashtag prediction machine learning project"},{"@type":"BreadcrumbList","@id":"https:\/\/techvidvan.com\/tutorials\/twitter-hashtag-prediction-machine-learning\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/techvidvan.com\/tutorials\/"},{"@type":"ListItem","position":2,"name":"Twitter Hashtag Prediction Project using Machine learning"}]},{"@type":"WebSite","@id":"https:\/\/techvidvan.com\/tutorials\/#website","url":"https:\/\/techvidvan.com\/tutorials\/","name":"TechVidvan Blogs","description":"","publisher":{"@id":"https:\/\/techvidvan.com\/tutorials\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/techvidvan.com\/tutorials\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/techvidvan.com\/tutorials\/#organization","name":"TechVidvan","url":"https:\/\/techvidvan.com\/tutorials\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/techvidvan.com\/tutorials\/#\/schema\/logo\/image\/","url":"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/2024\/03\/techvidvan-logo-200x50-1.webp","contentUrl":"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/2024\/03\/techvidvan-logo-200x50-1.webp","width":200,"height":50,"caption":"TechVidvan"},"image":{"@id":"https:\/\/techvidvan.com\/tutorials\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/TechVidvan\/","https:\/\/x.com\/vidvantech"]},{"@type":"Person","@id":"https:\/\/techvidvan.com\/tutorials\/#\/schema\/person\/e9c26e74dd3d87421f7ada9433b8cd22","name":"TechVidvan Team","description":"The TechVidvan Team delivers practical, beginner-friendly tutorials on programming, Java, Python, C++, DSA, AI, ML, data Science, Android, Flutter, MERN, Web Development, and technology. Our experts are here to help you upskill and excel in today\u2019s tech industry."}]}},"amp_enabled":false,"_links":{"self":[{"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/posts\/85712","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/comments?post=85712"}],"version-history":[{"count":0,"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/posts\/85712\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/media\/85732"}],"wp:attachment":[{"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/media?parent=85712"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/categories?post=85712"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/tags?post=85712"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}