Lesson

Endorsement

In the previous lesson Full definition for betweenness centrality (opens in a new tab)A score for each node equal to how often it lies on the shortest paths between other nodes. scored every person by how many shortest paths run through them.

Algorithms in the Endorsement family score Full definition for node (opens in a new tab)A vertex in a graph. In a property graph it can carry labels and properties. based on the scores of the nodes that connect to that node.

Eigenvector Full definition for centrality (opens in a new tab)How important a node is within a graph. Each centrality algorithm defines importance differently., Full definition for PageRank (opens in a new tab)A centrality algorithm that scores a node by the number of nodes pointing at it and by how important those nodes are., Article Rank and HITs are the four algorithms in this family.

The first three are variations on the same idea. HITs reaches the same kind of answer by holding two scores per node instead of one.

In this lesson, you'll:

  • Run each algorithm on the messaging network
  • Use each algorithm's results to create a comparative ranking
  • Compare multiple scores from across the graph

By the end of this lesson, you will understand when and how to analyze a graph with algorithms from the Endorsement family.

What Endorsement algorithms do

Endorsement algorithms aim to score nodes higher based on the scores of nodes that point to them.

In this example graph, Declan's node would receive the highest score from Eigenvector Centrality, PageRank and Article Rank.

HITs would provide a slightly different answer. It provides two scores, and Odette would rank highest on one of them. We'll come back to HITs later in the lesson. For now, you'll focus on the three direct siblings: Eigenvector, PageRank and Article Rank.

Endorsement scores by hand

We can work out a simple Endorsement score quite easily by hand.

Let's say that all nodes start with a score of 1.0.

  • Odette receives three votes, one each from Ingrid, Magnus and Yusuf, so Odette scores 1.0 + 1.0 + 1.0 = 3.0.
  • Declan receives a vote from Odette and one from Sana, so Declan scores 3.0 + 1.0 = 4.0.

The following table shows the actual scores produced by Eigenvector, PageRank and Article Rank in their default settings:

NameEigenvectorPageRankArticle Rank
Declan0.9970.7300.386
Odette0.0750.5330.359
Ingrid0.0010.1500.150
Magnus0.0010.1500.150
Yusuf0.0010.1500.150
Sana0.0010.1500.150

You should notice, while each algorithm produces a different score, the rank order remains consistent.

While each of these algorithms attempts to perform the same task, their biases and arithmetic differ in subtle ways.

Next, you'll take a look at their behaviors in greater detail.

Look again at the incoming messages query

In the Explore the graph lesson you ran this query for Person 1566.

Run it again, now.

cypher:The query you ran in the Explore the graph lesson
MATCH path = (:Person)-[:MESSAGED]->(:Person)-[:MESSAGED]->(:Person {id: '1566'}) // (1)
RETURN path
  1. 1

    Two steps of incoming messages, both pointing towards one (:Person) node

It returns four direct correspondents, and 119 (:Person) nodes feeding into them. To see how "important" they are the broader network, let's run some algorithms.

Eigenvector Centrality

Eigenvector Centrality is the plainest form of endorsement: a node's score is the sum of its senders' own scores, with no other adjustment.

Run it now, on the directed Full definition for projection (opens in a new tab)An in-memory copy of part of your database that graph algorithms run against. You choose which nodes and relationships it holds..

cypher:Eigenvector Centrality
CALL gds.eigenvector.write( // (1)
  'directed', // (2)
  { writeProperty: 'eigenvector' } // (3)
)
YIELD nodePropertiesWritten // (4)
RETURN nodePropertiesWritten
  1. 1

    Runs Eigenvector Centrality and writes each score back to AuraDB instead of returning it

  2. 2

    The projection to read the graph from

  3. 3

    The property every :Person is given, holding their score

  4. 4

    How many (:Person) nodes were given the property

Your output should look something like this:

nodePropertiesWritten
1899

Every (:Person) node now carries an eigenvector score.

Read the eigenvector scores back

Run the following query to rank people by their eigenvector scores.

cypher:Rank people by eigenvector score
MATCH (p:Person)
RETURN p.id AS person, round(1000 * p.eigenvector) / 1000 AS eigenvector
ORDER BY eigenvector DESC
LIMIT 6

Your output should look something like this:

personeigenvector
16240.466
3980.296
1050.264
11680.247
3230.204
5570.158

Person 1624 tops this ranking by a wide margin. Back when you ran Full definition for degree centrality (opens in a new tab)A score for each node equal to its number of outgoing relationships., Person 1624 did not appear in the top rankings at all.

Person 398 comes in second place.

Why 1624 tops Eigenvector Centrality

Now, let's take a look at Person 1624 and Person 398 in their contexts.

The following query returns both, along with Person 32 for comparison.

cypher:View Person 1624
MATCH path = (:Person {id: '1624'})-[:MESSAGED]-(:Person)
RETURN path
UNION
MATCH path = (:Person {id: '398'})-[:MESSAGED]-(:Person)
RETURN path
UNION
MATCH path = (:Person {id: '32'})-[:MESSAGED]-(:Person)
RETURN path

What the visualisation shows

From the returned graph, you should notice a number of things:

  1. 1624 has many more recursive link paths back to itself
  2. 398 also has quite a few recursive paths back to itself
  3. 32 mostly connects out to other nodes, receiving comparatively few votes in return

a graph visualization of nodes 1624, 398 and 32.

Consider this result in line with the results from Betweenness Centrality—where Person 32 outranked all others.

32 was more influential as a gatekeeper. These nodes are more influential as endorsers — or "influencers" in a social media context.

How Eigenvector calculates scores

Eigenvector Centrality repeats one simple step, over and over. Eventually, the scores stop moving between rounds. That is convergence.

  1. Every node starts with a score of 1.0.
  2. On each round, a node's new score becomes the sum of its senders' current scores.
  3. After each round, Go to glossary for graph data science (opens in a new tab)Analysing data through the structure of its connections. Also the name of the Neo4j library that implements it. divides every score by the L2 norm of the whole set. That is not the same as the scores summing to 1.0 — it fixes the vector's Euclidean length at 1.0, not its total.

1624 and 398 both have paths that loop back to themselves, so on each iteration, they bump each others' scores.

a loop of 398 providing eigenvector votes to 1624 and vice versa.

Nothing in the three steps above stops that pair from boosting each other every round. That compounding is what carries 1624 and 398 to the top of the ranking.

It is also at least partially why PageRank exists.

PageRank

PageRank keeps Eigenvector's step and adds two adjustments to it:

A node drawing score from the nodes pointing at it, each of which draws from its own.

  1. It divides each sender's score by that sender's outgoing count, so somebody who sent 200 messages passes on a two-hundredth of their score along each one.
  2. It splits every score into an inherited part and a granted part. 85% is inherited from the senders pointing at the node, and the remaining 15% is granted to every node unconditionally.

The second adjustment is called the damping factor, and it can be reconfigured arbitrarily — which can result in wildly varying scores. You'll learn more about the nuances of PageRank in later labs.

Run PageRank now, on the directed projection, writing scores to a pageRank Full definition for property (opens in a new tab)A named value stored on a node or a relationship.. Try it yourself first, without checking the solution below.

Solution
cypher:PageRank
CALL gds.pageRank.write( // (1)
  'directed', // (2)
  { writeProperty: 'pageRank' } // (3)
)
YIELD nodePropertiesWritten // (4)
RETURN nodePropertiesWritten
  1. 1

    Runs PageRank and writes each score back to AuraDB instead of returning it

  2. 2

    The projection to read the graph from

  3. 3

    The property every :Person is given, holding their score

  4. 4

    How many (:Person) nodes were given the property

Your output should look like this:

nodePropertiesWritten
1899

Read the PageRank scores back

Every (:Person) node now carries a pageRank score alongside its eigenvector score.

Run the following query to rank nodes by PageRank.

cypher:Rank people by PageRank score
MATCH (p:Person)
RETURN p.id AS person,
       round(1000 * p.pageRank) / 1000 AS pageRank,
       round(1000 * p.eigenvector) / 1000 AS eigenvector
ORDER BY pageRank DESC
LIMIT 6

Your output should look something like this:

personpageRankeigenvector
328.7060.11
3238.6290.204
3727.7080.081
1037.2820.092
16247.0410.466
426.2960.061

Person 1624 is still here, in fifth place. Dividing each sender's score by the number of messages that sender wrote has cost the pair their compounding advantage.

Article Rank

Article Rank takes PageRank's division one step further.

PageRank divides a sender's score by that sender's own outgoing count. Article Rank divides it by that count plus the average outgoing count across the whole graph.

In your CollegeMsg graph, a sender who wrote thirty messages sits near that average, so the extra term changes little. A sender who wrote only one message receives a heavy penalty to their score.

Run it now on the directed projection, writing to an articleRank property.

cypher:Article Rank
CALL gds.articleRank.write( // (1)
  'directed', // (2)
  { writeProperty: 'articleRank' } // (3)
)
YIELD nodePropertiesWritten // (4)
RETURN nodePropertiesWritten
  1. 1

    Runs Article Rank and writes each score back to AuraDB instead of returning it

  2. 2

    The projection to read the graph from

  3. 3

    The property every :Person is given, holding their score

  4. 4

    How many (:Person) nodes were given the property

Now rank your nodes by their Article Rank scores.

cypher:Rank people by Article Rank score
MATCH (p:Person)
RETURN p.id AS person,
       round(1000 * p.articleRank) / 1000 AS articleRank,
       round(1000 * p.pageRank) / 1000 AS pageRank,
       round(1000 * p.eigenvector) / 1000 AS eigenvector
ORDER BY articleRank DESC
LIMIT 6

Your output should look something like this:

personarticleRankpageRankeigenvector
3231.5468.6290.204
321.3408.7060.11
16241.3217.0410.466
3721.2767.7080.081
1031.2437.2820.092
4541.0746.1030.047

The scores are much smaller than PageRank's, because every sender's contribution is divided by a larger number.

Person 323 sits fifth on Eigenvector, second on PageRank, and first here.

The same six people, on one scale

The three scores use different scales, so a number from one means nothing beside a number from another.

The table below presents the same six nodes, with each column scaled so the highest score in the graph reads 1 and the lowest reads 0.

personeigenvectorpageRankarticleRank
3230.4370.9921.0
320.2361.00.853
16241.00.8060.839
3720.1730.8830.807
1030.1980.8340.783
4540.1010.6660.662

Person 1624 holds the top eigenvector score and 0.806 of the top PageRank score. Person 32 reverses that, on 0.236 and 1.0.

Which of the three to run

Each algorithm decides how much a single endorsement is allowed to carry.

Eigenvector passes a sender's score on whole. Somebody endorsed by two or three heavily endorsed senders scores highly. Run Eigenvector when every node's vote remains the same regardless of how many votes they give.

For example, a person with an infectious disease does not lose their infectiousness the more they infect others, so, in a contact-tracing graph, Eigenvector could make more sense than PageRank.

Bridget infected four people and Dmitri infected one. All five carry the same exposure, because what Bridget passes on is not divided by the number of people Bridget met.

PageRank divides a sender's score by the number of messages that sender wrote. An endorsement from somebody who wrote to four hundred people is worth a four-hundredth of one from somebody who wrote to one. Run PageRank when a node holds a fixed amount of influence and splits it between everybody it votes for.

For example, a social media user who likes everything may be considered to have less endorsement value per like than someone else who likes only a curated selection.

Bridget and Dmitri hold the same score to give. Bridget likes four posts and passes a quarter of it to each — Dmitri likes one post and passes all of it.

Article Rank adds the graph's average outgoing count to PageRank's divisor. In our messaging graph, under PageRank, a person who sent one message hands their whole score to one recipient, and a thirty-second of it under Article Rank. Run Article Rank when a node with very few votes should not decide the ranking on its own.

For example, a reviewer who has rated a single film should not carry more weight per rating than a critic who has rated hundreds. Article Rank inverts PageRank's low-relationship, single-authority bias.

By PageRank

By Article Rank

Under PageRank the Newcomer's single rating carries three times the weight of any one of the Critic's. Article Rank adds the average outgoing count to both divisors, so in a graph where people rate many films the Newcomer's voting power will be dampened relative to the average.

HITs

HITs asks the same question as the other three, and answers it with two scores per node rather than one:

  • Authority: How much link juice a node receives from other nodes that are recognized as Hubs
  • Hub: How much authority this node can pass to other nodes

Notice here that Eigenvector, PageRank and Article Rank all use one score to influence neighbors' scores.

HITs does not. Any single node's current score can only be influenced by its neighbors' opposing scores.

On each iteration, a node receives another update to both its Authority score and Hub score, in that order:

  • Authority: A node's authority score is updated by the sum of the hub scores of nodes that point into it.
  • Hub: A node's Hub score is updated by the sum of the Authority scores of the nodes it points into.

Take a look at the same graph, updated in two steps:

Authority update

Hub update

The Authority update identifies Odette as the highest authority node. The Hub update identifies Ingrid, Magnus and Yusuf as tied for the most important Hub nodes.

HITs by hand

We can similarly work this out, for one iteration, by hand. Let's say every node starts with a hub score and an authority score of 1.0.

Authority update:

  • Odette receives three votes, one each from Ingrid, Magnus and Yusuf.
  • Odette then, has an authority score of 1.0 + 1.0 + 1.0 = 3.0.
  • Declan receives two votes, from Odette and Sana. Declan then, has an authority score of 1.0 + 1.0 = 2.0.

Hub update:

  • Ingrid, Magnus, and Yusuf each point at Odette alone, so they each receive her authority score of 3.0.
  • Odette and Sana both point at Declan alone, so they both get Declan's new authority score of 2.0.

If we run this same calculation 20 times in a row, the values of each will stop moving, and we will have converged.

Run HITs

HITs holds two scores per node, so it streams a map of values rather than writing a single property.

HITs is not currently available in Go to glossary for Aura Graph Analytics (opens in a new tab)The Aura service that runs graph algorithms in a separate session, with no plugin to install., except via the graphdatascience driver or the GDS plugin. The code below demonstrates how to run it in either.

python:HITs
hits = gds.hits.stream(G_directed, hitsIterations=20) # (1)
print(hits.head()) # (2)
  1. 1

    Twenty rounds of the authority update followed by the hub update

  2. 2

    One row per person, holding a values map with both scores

On the current graph, your output would look like this:

personauthorityhub
5690.4300.019
11180.2580.015
13120.2480.038
16240.2270.119
80.1820.009
2820.1690.004

Person 1624 is the only name here that also appeared in the first three rankings.

A high authority score and a low hub score describe somebody the network writes to far more than they write out.

Other considerations

As with all algorithms, the meaning of an Endorsement result will change based on the analyzed graph.

For instance, had you run these algorithms on the undirected projection, every endorsement would also count backwards along the message that carried it. PageRank on an Full definition for undirected relationship (opens in a new tab)A relationship with no direction. Neo4j GDS represents them as parallel relationships in opposite directions. graph often degrades to the same ranking as Degree Centrality.

Similarly, PageRank's damping factor is a setting you choose, so the same graph can produce more than one ranking.

Later, you will learn more about the nuances and differences between each of these algorithms in their dedicated labs.