HITS Algorithm: Link Analysis Explanation and Python Implementation from Scratch | by Chonyy | Towards Data Science

We use the search engine in our daily life, but have you ever wonder how the search engine finds the ideal site that you are looking for? It’s far more complicated than a simple text search. For example, if we are looking for a website about an apple, will a website full of the word “apple ” be on top of Google search results?
Hyperlink Induced Topic Search (HITS) is an algorithm used in link analysis. It could discover and rank the webpages relevant for a particular search. The idea of this algorithm originated from the fact that an ideal website should link to other relevant sites and also being linked by other important sites. We will briefly introduce the algorithm and walkthrough the Python code implementation in this post.
Feel free to check out the well-commented source code. It could really help to understand the whole algorithm.
github.com
First, we have to explain what is authority and hub. HITS uses hubs and authorities to define a recursive relationship between webpages.
Authority: A node is high-quality if many high-quality nodes link to it
Hub: A node is high-quality if it links to many high-quality nodes
Initialize the hub and authority of each node with a value of 1
For each iteration, update the hub and authority of every node in the graph
The new authority is the sum of the hub of its parents
The new hub is the sum of the authority of its children
Normalize the new authority and hub
We initialize the hub and authority in the Node constructor. The initial value of auth and hub is 1.
This is the HITS algorithm's main function. As you can see, it’s really nice and short. The logic in it follows the algorithm I mentioned above.
For every node in the graphUpdate authorityUpdate hubNormalize the updated value
For every node in the graph
Update authority
Update hub
Normalize the updated value
New auth = the sum of the hub of all of its parents
New hub = the sum of the auth of all of its children
Normalize authority with the sum of auth of all nodes in the graph
Normalize hub with the sum of hub of all nodes in the graph
Let’s test our implementation on the dataset in the repo.
Result
The result follows the order of node value, which is 1, 2, 3, 4, 5, 6 . Recall from the explanation above, authority depends on how many nodes link to it, hub depends on how many nodes it links to.
From the result, we could tell that this rule holds. The authority of node 1 is 0 because there is no node link to it. The hub of node 6 is 0 because it doesn’t link to any node.
Result
Similarly, this answer totally makes sense. The nodes form a cycle. They all have one parent and one child, and connected to each other. In the link perspective, they are basiclly all the same. That’s why they all have same authority and hub value.
Result
Node2, Node3  - How many nodes link to it: 2  - How many nodes it links to: 2Node1, Node4  - How many nodes link to it: 1  - How many nodes it links to: 1
This is why node2 and node3 have a higher authority and hub value.
Result
There’s an interesting observation happens here. Let’s take a look at the authority of node3 and node5. They are both 0.201. There are four nodes linking to node5 and only three nodes linking to node3. But they have the same authority! Why’s that?
This is because node5 has a higher hub than node6 and node7. So node3 only needs node5 to get the same value of linking by node6 and node7.
Result
The result follows the node value order 2076, 2564, 4785, 5016, 5793, 6338, 6395, 9484, 9994 .
Let’s take a look at the authority of node4785, node5016, node6338. They all have the same auth value 0.105. This is because they all have a single and common parent node2076.
Now then observe the hub values. Node2076 has the highest hub. This is because it has linked to every node in the graph. Node4785, node5016, node6338 has a hub value of 0 because they have absolutely no child to link to.
Let’s run an interesting experiment. Assume that we want to increase the hub and authority of node1 in each graph. How can we do it?
Hub is like the power of linking to other nodes. So we simply have to make node1 link to one more node to increase its hub. By adding edge (node1, node6), the hub value greatly increased 0.2 -> 0.618.
Authority is like the power of being linked. We add the edge (node5, node1), the authority value greatly increased 0 -> 0.5.
The original graph is a cycle, which has all equal authority and hub. By adding an extra edge (node1, node4), we increased the power of node1 linking to others. Thus, the hub value is increased.
Similarly, we increased node1’s power of being linked by adding an extra edge (node4, node1). Now, node1 has two parents. Therefore, its authority is increased.
Comparing to the original graph. We add an edge (node1, node4) in the left graph and an edge (node4, node1) in the right graph. Just like the logic we implemented on the graphs above, we add those two edges to increase hub and authority respectively.
Now we all knew that after enough iterations, hub and authority will always converge to a specific value. Why don’t we plot it out to check how fast it’s converging?
Testing the convergence on graph_4.txt
From the plot, we can see that the authority and hub start to converge at iteration 5. This computation time is fair enough for a not-so-simple graph. However, the iteration needed could largely increase when there are more nodes and edges in the graph.
For example, 500 iterations are still not enough for graph_6.txt, which has 1228 nodes, 5220 edges in it. And the computation time takes forever long due to a large number of edges.
We run 100 iterations with a different number of total edges in order to spot the relation between total edges and computation time. As you can see, the inference of edges number on the computation time is almost linear, which is pretty good I’ll say.
Please note that the reason it’s not completely linear is the way the edges link to each other will also affect the computation time a little.
The major shortcoming of the HITS algorithm is it is query-dependent. From the original paper, the link analysis is started from the root set retrieved from some traditional text-based search algorithm. Then expand the sites the root set links to, which is the base set.
This could be troublesome since the result from link analysis could be affected by the initial search algorithm. And the evaluation time of the text-based search is super expensive.
Therefore I would like to introduce another query-independent link analysis algorithm, PageRank algorithm. Feel free to check it out!
chonyy.medium.com
Also, if you are interested in measuremt of Similarity in link analysis.