NETWORK Procedure
Example 2.20 Node Embeddings for European Roads Data
This example uses a European roads data set that is maintained by the Neo4j graph embeddings tutorial (Needham 2020). The graph includes 1,250 roadway connections among 894 cities and towns. You can compute node embeddings for these places by using vector node similarity. To simplify visualization, you can limit the data set to the seven most populous European countries: Spain, Great Britain, France, Turkey, Italy, Germany, and Greece. The graph is shown in Figure 247.
Figure 247: European Roads Graph

You can represent the graph by using the following links data table, mylib.LinkSetIn. The following statements create the data table mylib.Roads from a local copy of the raw European roads data:
filename in 'roads.csv';
data mylib.Roads;
infile in missover firstobs = 2 DSD;
length from to $40;
input
road_number $
from_country $
from $
to_country $
to $
distance
watercrossing $;
run;
The following statements construct the nodes and links data tables, mylib.Nodes and mylib.Links, from the raw roads data:
%let country_subset = ("E", "GB", "F", "TR", "I", "D", "GR");
data mylib.nodes;
set mylib.Roads(
rename=(from=node from_country=country)
)
mylib.Roads(
rename=(to=node to_country=country)
);
by country node;
if FIRST.node
and country in &country_subset;
if country EQ 'D' then color=1;
else if country EQ 'E' then color=2;
else if country EQ 'F' then color=3;
else if country EQ 'GB' then color=4;
else if country EQ 'GR' then color=5;
else if country EQ 'I' then color=6;
else if country EQ 'TR' then color=7;
keep node country color;
run;
data mylib.Links;
set mylib.Roads;
where from_country in &country_subset and to_country in &country_subset;
run;
The following statements use the EMBED=TRUE option to generate node embeddings for the European roads data:
proc network
links = mylib.Links
nodes = mylib.Nodes
outNodes = mylib.OutNodesEmb;
nodesVar
vars = (country color);
nodeSimilarity
jaccard = false
embed = true
nDimensions = 300
proximityOrder = first
nSamples = 10000000;
run;
The output data table mylib.OutNodesEmb contains the embedding vectors for each node. The first three components of five sample node embedding vectors are shown in Output 2.20.1.
Output 2.20.1: Embedding Vectors Output
| node | vec_1 | vec_2 | vec_3 |
|---|---|---|---|
| Alessandria | -0.04285 | 0.015841 | 0.048797 |
| Belfast | 0.19921 | 0.012813 | -0.057647 |
| Hamburg | -0.02078 | 0.060347 | -0.045608 |
| Milano | -0.00585 | 0.011605 | 0.018188 |
| Rennes | 0.00620 | -0.062755 | -0.047990 |
For ease of visualization, it is common practice to collapse the multidimensional embeddings down to two dimensions. You can achieve this by using the TSNE procedure.
The following PROC TSNE statements produce a two-dimensional representation of the node embeddings:
proc tsne
seed = 1
data = mylib.OutNodesEmb
nDimensions = 2
perplexity = 15
maxIters = 3000;
input vec_:;
output
out = mylib.OutNodesTsne
copyvars = (node country color);
run;
For validation, you can visualize the node embeddings. You can plot the two-dimensional embeddings representation, colored by country, by using the following PROC TEMPLATE and PROC SGRENDER statements:
proc template;
define statgraph vectorPlot;
begingraph;
entrytitle "TSNE Embeddings Colored by Country: Vector";
legendItem type=marker name="d" /
markerattrs=(color=CX7FC97F symbol=circlefilled)
label="Germany" ;
legendItem type=marker name="e" /
markerattrs=(color=CXBEAED4 symbol=circlefilled)
label="Spain" ;
legendItem type=marker name="f" /
markerattrs=(color=CXFDC086 symbol=circlefilled)
label="France" ;
legendItem type=marker name="gb" /
markerattrs=(color=CXFFFF99 symbol=circlefilled)
label="Great Britain" ;
legendItem type=marker name="gr" /
markerattrs=(color=CX386CB0 symbol=circlefilled)
label="Greece" ;
legendItem type=marker name="i" /
markerattrs=(color=CXF0027F symbol=circlefilled)
label="Italy" ;
legendItem type=marker name="tr" /
markerattrs=(color=CXBF5B17 symbol=circlefilled)
label="Turkey" ;
layout overlay /
yaxisopts=(labelFitPolicy=Split)
y2axisopts=(labelFitPolicy=Split);
ScatterPlot X=_DIM_1_ Y=_DIM_2_ /
markerattrs=(symbol=circlefilled size=10)
colormodel=(CX7FC97F CXBEAED4 CXFDC086 CXFFFF99 CX386CB0 CXF0027F CXBF5B17)
colorresponse=color
name="scatter";
discretelegend "d" "e" "f" "gb" "gr" "i" "tr";
endlayout;
endgraph;
end;
run;
proc sgrender data=mylib.OutNodesTsne template=vectorPlot; /* use GTL template */
run;
Output 2.20.2: TSNE Representation of Vector Node Embeddings

In the plot shown in Output 2.20.2, note that the nodes representing places within the same country (color) appear to be clustered together in the embedded vector space.
The embeddings that are learned by using vector node similarity are functionally similar to the alternative techniques DeepWalk (Perozzi, Al-Rfou, and Skiena 2014; Perozzi 2014) and Node2Vec (Grover and Leskovec 2016; Grover 2016). Although these alternatives are not currently supported in PROC NETWORK, the results are provided here for comparison. The results that are obtained by DeepWalk for the same graph are shown in Output 2.20.3, and the results that are obtained by Node2Vec for the same graph are show in Output 2.20.4.
Output 2.20.3: TSNE Representation of DeepWalk Node Embeddings

Output 2.20.4: TSNE Representation of Node2Vec Node Embeddings
