Package: graphrole
GraphRoleAutomatic feature extraction and node role assignment for transfer learning on graphs; based on the ReFeX/RolX algorithms [1, 2] of Henderson, et al.OverviewA fundamental problem for learning on graphs is extracting meaningful features.GraphRoleprovides theRecursiveFeatureExtractorclass to automate this process by extracting recursive features capturing local and neighborhood ("regional") structural properties of a given graph.  The specific implementation follows that of the ReFeX algorithm [1].  Node features (e.g., degree) and ego-net features (e.g., neighbors, number of internal vs. external edges) are extracted and then recursively aggregated over each node's neighbors' features until no additional information is encoded.  As is shown in [1], these recursive, "regional" features facilitate node classification and perform quite well in transfer learning tasks.GraphRolealso provides theRoleExtractorclass for node role assignment (a form of classification).  Different nodes play different structural roles in a graph, and using recursive regional features, these roles can be identified and assigned to collections of nodes.  As they are structural in nature, node roles differ from and are often more intuitive than the commonly used communities of nodes.  In particular, roles can generalize across graphs whereas the notion of communities cannot [2].  Identification and assignment of node roles has been shown to facilitate many graph learning tasks.Please see [1, 2] for more technical details.InstallationThis package is hosted on PyPI and can be installed viapip:$ pip install graphroleTo instead install from source:$ git clone https://github.com/dkaslovsky/GraphRole.git
$ cd GraphRole
$ python setup.py installExampleAn example ofGraphRoleusage is found in theexamplesdirectory.  The notebookexample.ipynb(also available vianbviewer)
walks through feature extraction and role assignment for the well-knownkarate_club_graphthat is included withNetworkX.  Recursive features are extracted and used to learn role assignments for each node in the graph.  The graph is shown above with each node colored corresponding to its role.The extracted roles reflect structural properties of the graph at the node level.  The nodes0and33(dark green) are central to the graph and are connected to many other nodes.  Nodes1,2,3, and32are assigned to a similar role (red).  In contrast, the roles colored as dark blue, light blue, and pink are found at the periphery of the graph.  Notably, nodes need not be near one another to be assigned to the same role; instead nodes with similar properties are grouped together across the graph by their role assignments.Although not reflected by this example, weighted and directed graphs are also supported and will yield weighted and directed variants of the extracted features.UsageFor general usage, begin by importing the two feature and role extraction classes:>>>fromgraphroleimportRecursiveFeatureExtractor,RoleExtractorFeatures are then extracted from a graphGinto apandas.DataFrame:>>>feature_extractor=RecursiveFeatureExtractor(G)>>>features=feature_extractor.extract_features()Next, these features are used to learn roles.  The number of roles is automatically determined by
a model selection procedure whenn_roles=Noneis passed to theRoleExtractorclass instance.
Alternatively,n_rolescan be set to a desired number of roles to be extracted.>>>role_extractor=RoleExtractor(n_roles=None)>>>role_extractor.extract_role_factors(features)The role assignment for each node can be retrieved as a dictionary:>>>role_extractor.rolesAlternatively, roles can be viewed as a soft assignment and a node's percent membership to each role
can be retrieved as apandas.DataFrame:>>>role_extractor.role_percentageNode Attributes as User-Defined FeaturesGraphRoleuses predefined structural graph properties for constructing features. It is also possible, as of version 1.1.0, to optionally include numeric node attributes as features. Providing a graph annotated with node attributes toGraphRoleallows a user to seed the recursive feature extraction process with user-defined features for each node.Node attributes are enabled by passingattributes=Trueas a kwarg to theRecursiveFeatureExtractor:>>>feature_extractor=RecursiveFeatureExtractor(G,attributes=True)Providing this kwarg will automatically include all numeric node attributes as features to be included in the recursive feature calculations. Attributes with non-numeric values are always skipped (set to zero). Note that the feature names associated with node attributes will be the provided attribute name prepended with a prefix ofattribute_.A list of attributes to be included for feature calculation instead of defaulting to all numeric attributes can be provided as:>>>feature_extractor=RecursiveFeatureExtractor(G,attributes=True,attributes_include=['attr1','attr3'])which will specify the use of only node attributesattr1andattr3.A list of attributes to be excluded for feature calculation from the default of all numeric attributes can be provided as:>>>feature_extractor=RecursiveFeatureExtractor(G,attributes=True,attributes_exclude=['attr2'])which will specify the use of all node attributes other thanattr2.For safety, theattributes_excludelist takes priority over theattributes_includelist when conflicting specifications are provided.Note:igraphuses the attributenameto store an identifier for all nodes and therefore the corresponding attribute value is never used for feature calculations. The attributename, even if overwritten by the user, is always skipped forigraphgraph instances.Graph InterfacesAn interface for graph data structures is provided in thegraphrole.graph.interfacemodule.  Implementations fornetworkxandigraphare included.Theigraphpackage is not included inrequirements.txtand thus will need to be manually installed
if desired.  This is due to additional installation requirements beyondpip install python-igraph; see
theigraph documentationfor more details.  Note that all tests
that requireigraphwill be skipped if it is not installed.To add an implementation of an additional graph library or data structure:Subclass theBaseGraphInterfaceABC ingraphrole.graph.interface.base.pyand implement the required methodsUpdate theINTERFACESdict ingraphrole.graph.interface.__init__.pyto make the new subclass discoverableAdd tests by trivially implementing asetUpClass()classmethod of a subclass ofBaseGraphInterfaceTest.BaseGraphInterfaceTestCasesin thetests.test_graph.test_interface.pymoduleIf desired, a similar procedure allows the feature extraction tests to be run using the added interface
by again trivially implementing asetUpClass()classmethod of a subclass ofBaseRecursiveFeatureExtractorTest.TestCasesin thetests.test_features.test_extract.pymoduleFuture DevelopmentModel explanation ("sense making") will be added to theRoleExtractorclass in a future release.TestsTo run tests:$ python -m unittest discover -vAs noted above, the tests for theigraphinterface are skipped whenigraphis not installed.  Because this package is intentionally not required, the  test coverage reported above is much lower than whenigraphis installed and its interface tests are not skipped (97% coverageto date).References[1] Henderson, et al.It’s Who You Know: Graph Mining Using Recursive Structural Features.[2] Henderson, et al.RolX: Structural Role Extraction & Mining in Large Graphs.