<jupyter_start><jupyter_text>Normalizing features<jupyter_code>node_features_df['normalized_alexa_rank'] = node_features_df['alexa_ranks'].apply(lambda x: 1/x if x else 0)
import math

node_features_df['normalized_total_sites_linked_in'] = node_features_df['total_sites_linking_ins'].apply(lambda x: math.log2(x) if x else 0)<jupyter_output><empty_output><jupyter_text>---<jupyter_code>edge_df = pd.read_csv(edge_file)

edge_df.head()
edge_df.info()
import stellargraph as sg
G = sg.StellarGraph(node_features_df[['normalized_alexa_rank', 'normalized_total_sites_linked_in']], edge_df)
print(G.info())<jupyter_output>StellarGraph: Undirected multigraph
 Nodes: 11865, Edges: 20399

 Node types:
  default: [11865]
    Features: float32 vector, length 2
    Edge types: default-default->default

 Edge types:
    default-default->default: [20399]
        Weights: all 1 (default)
        Features: none<jupyter_text>Unsupervised Attrib2Vec<jupyter_code>from stellargraph.mapper import Attri2VecLinkGenerator, Attri2VecNodeGenerator
from stellargraph.layer import Attri2Vec, link_classification
from stellargraph.data import UnsupervisedSampler

from tensorflow import keras<jupyter_output><empty_output><jupyter_text>1. Specify the other optional parameter values:* root nodes* the number of walks to take per node* the length of each walk* random seed<jupyter_code>nodes = list(G.nodes())
number_of_walks = 10
length = 100<jupyter_output><empty_output><jupyter_text>2. Create the UnsupervisedSampler instance with the relevant parameters passed to it.<jupyter_code>unsupervised_samples = UnsupervisedSampler(
    G, nodes=nodes, length=length, number_of_walks=number_of_walks
)<jupyter_output><empty_output><jupyter_text>3. Create a node pair generator:<jupyter_code>batch_size = 50
# epochs = 4
num_samples = [10, 5]
generator = Attri2VecLinkGenerator(G, batch_size)
train_gen = generator.flow(unsupervised_samples)
layer_sizes = [128]
attri2vec = Attri2Vec(layer_sizes=layer_sizes, generator=generator, bias=False, normalize=None)
# Build the model and expose input and output sockets of attri2vec, for node pair inputs:
x_inp, x_out = attri2vec.in_out_tensors()
prediction = link_classification(
    output_dim=1, output_act="sigmoid", edge_embedding_method="ip"
)(x_out)
model = keras.Model(inputs=x_inp, outputs=prediction)

model.compile(
    optimizer=keras.optimizers.Adam(lr=1e-3),
    loss=keras.losses.binary_crossentropy,
    metrics=[keras.metrics.binary_accuracy],
)
history = model.fit(
    train_gen,
    epochs=8,
    verbose=2,
    use_multiprocessing=False,
    workers=1,
    shuffle=True,
)

"""
1. (run) previous before normalization

WARNING:tensorflow:sample_weight modes were coerced from
  ...
    to  
  ['...']
Train for 1899 steps
Epoch 1/8
1899/1899 - 47s - loss: 0.7380 - binary_accuracy: 0.5427
Epoch 2/8
1899/1899 - 46s - loss: 0.6368 - binary_accuracy: 0.6424
Epoch 3/8
1899/1899 - 47s - loss: 0.5929 - binary_accuracy: 0.6680
Epoch 4/8
1899/1899 - 48s - loss: 0.5694 - binary_accuracy: 0.6800
Epoch 5/8
1899/1899 - 52s - loss: 0.5564 - binary_accuracy: 0.6865
Epoch 6/8
1899/1899 - 47s - loss: 0.5442 - binary_accuracy: 0.6933
Epoch 7/8
1899/1899 - 48s - loss: 0.5399 - binary_accuracy: 0.6941
Epoch 8/8
1899/1899 - 47s - loss: 0.5272 - binary_accuracy: 0.7013

2 (run) after normalization but without parameters tuning

WARNING:tensorflow:sample_weight modes were coerced from
  ...
    to  
  ['...']
Train for 1899 steps
Epoch 1/8
1899/1899 - 49s - loss: 0.6926 - binary_accuracy: 0.5304
Epoch 2/8
1899/1899 - 52s - loss: 0.6343 - binary_accuracy: 0.5872
Epoch 3/8
1899/1899 - 43s - loss: 0.6147 - binary_accuracy: 0.6016
Epoch 4/8
1899/1899 - 43s - loss: 0.5955 - binary_accuracy: 0.6457
Epoch 5/8
1899/1899 - 43s - loss: 0.5755 - binary_accuracy: 0.6763
Epoch 6/8
1899/1899 - 44s - loss: 0.5604 - binary_accuracy: 0.6914
Epoch 7/8
1899/1899 - 44s - loss: 0.5486 - binary_accuracy: 0.7005
Epoch 8/8
1899/1899 - 43s - loss: 0.5390 - binary_accuracy: 0.7082

"""
x_inp_src = x_inp[0]
x_out_src = x_out[0]
embedding_model = keras.Model(inputs=x_inp_src, outputs=x_out_src)
node_gen = Attri2VecNodeGenerator(G, batch_size).flow(node_features_df.index)
node_embeddings = embedding_model.predict(node_gen, workers=1, verbose=1)
node_embeddings[213]
embeddings_wv = dict(zip(node_features_df.index.tolist(), node_embeddings))
embeddings_wv['villagevoice.com']
class ModelWrapper:
    def __init__(self, embeddings_wv):
        self.wv = embeddings_wv
        
    def __str__(self):
        return 'Unsupervised Attrib2Vec'
import sys,os
sys.path.append("C:\\Users\\Paco\\Documents\\site_similarity")
from utils.notebook_utils import train_model
data_year = '2018'
node2vec_model = ModelWrapper(embeddings_wv)
! cd
%run ../../utils/notebook_utils.py
from sklearn import svm
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.linear_model import LogisticRegressionCV
result_report = []

clf = LogisticRegressionCV(Cs=10, cv=5, scoring="accuracy", multi_class="ovr", max_iter=300, random_state=42)
result_report.append([
    str(node2vec_model),
    'LogisticRegression CV = 5',
    *list(train_model(clf, node2vec_model=node2vec_model, data_year=data_year).values())
]);

clf2 = LogisticRegressionCV(Cs=10, cv=10, scoring="accuracy", multi_class="ovr", max_iter=300, random_state=42)
result_report.append([
    str(node2vec_model),
    'LogisticRegression CV = 10',
    *list(train_model(clf2, node2vec_model=node2vec_model, data_year=data_year).values())
]);

tree_clf = GradientBoostingClassifier(random_state=42)
result_report.append([
    str(node2vec_model),
    'GradientBoostingClassifier',
    *list(train_model(tree_clf, node2vec_model=node2vec_model, data_year=data_year).values())
]);

svm_clf = svm.SVC(decision_function_shape='ovo', probability=True, random_state=42)
result_report.append([
    str(node2vec_model),
    'SVC ovo',
    *list(train_model(svm_clf, node2vec_model=node2vec_model, data_year=data_year).values())
]);

model_res = pd.DataFrame(result_report,
                    columns=["Feature", "Classifier", "Accuracy", "Balanced Accuracy score",
                             "F1 micro score", "F1 macro score", "F1 weighted score", "MAE", "Confusion matrix"])
model_res.head()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11473583704646721, 'fraction_numerical': 0.07590706556333546, 'mean_word_length': 5.179941002949852, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '200248', 'license': 'MIT', 'n_tokens_mistral': 2629, 'n_tokens_neox': 2319, 'n_words': 473, 'path': 'notebooks/node_features_graphs/corpus 2018/Unsupervised Attrib2Vec corpus 2018 audience_overlap lvl data 1.ipynb', 'repo_name': 'PacoPacov/site_similarity', 'size': '6284'}