Skip to content

Commit

Permalink
Merge pull request #110 from BlankSpacePlus/main
Browse files Browse the repository at this point in the history
Reformat Python code based on PEP specification
  • Loading branch information
Arlen-yuzu committed Oct 5, 2023
2 parents ae2bca9 + 6af24e9 commit 58f5cb1
Show file tree
Hide file tree
Showing 95 changed files with 1,727 additions and 1,720 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ doc_html_auto_generator
.DS_Store
src/.DS_Store
result
data
data
.idea
30 changes: 17 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
<p align="center">
<a href="https://zhoushengisnoob.github.io/projects/DGLD_Fronted/index.html"> <img src="DGLD_logo.jpg" width="200"/></a>
<a href="https://zhoushengisnoob.github.io/projects/DGLD_Fronted/index.html"> <img src="images/DGLD_logo.jpg" width="200" alt="DGLD LOGO"/></a>
<p>

<h1 align="center">
<p>A Deep Graph Anomaly Detection Library <br> based on DGL</p>
</h1>
<h1 align="center">A Deep Graph Anomaly Detection Library <br> based on DGL</h1>

<p align="center">
<b> <a href="https://zhoushengisnoob.github.io/projects/DGLD_Fronted/index.html">Website</a> | <a href="https://zhoushengisnoob.github.io/DGLD/doc/docstring_html/html/dgld.html">Doc</a> </b>
</p>

DGLD is an open-source library for Deep Graph Anomaly Detection based on pytorch and DGL. It provides unified interface of popular graph anomaly detection methods, including the data loader, data augmentation, model training and evaluation. Also, the widely used modules are well organized so that developers and researchers can quickly implement their own designed models.


## News

* [Aug 2022] We have released an [easy-to-use graphical command line tool](https://zhoushengisnoob.github.io/DGLD/web/index.html) for users to run experiments with different models, datasets and customized parameters. Users can select all the settings in the page, click 'Submit' and copy the shell scripts to the terminal.
* [July 2022] For PyG users, we recommend the [PyGOD](https://github.com/pygod-team/pygod/), which is another comprehensive package that also supports many graph anomaly detection methods.
* [June 2022] Recently we receive feedback that the reported results are slightly different from the original paper. This is due to the anomaly injection setting, the graph augmentation and sampling. We will provide more details on the settings.

## Installation

Basic environment installation:
```shell
conda create -n dgld python=3.8.0
Expand All @@ -27,17 +26,22 @@ conda install cudatoolkit==11.3.1
pip install dgl-cu113==0.8.1 dglgo==0.0.1 -f https://data.dgl.ai/wheels/repo.html
pip install torch==1.11.0+cu113 -f https://download.pytorch.org/whl/torch_stable.html
```
- ### install from source code

### Install from source code

Then clone the DGLD project, enter the directory and run:
```shell
git clone git@github.com:EagleLab-ZJU/DGLD.git
pip install -r requirements.txt
```
To check whether you have successfully installed the package and environment, you can simply run

```shell
python example.py
```
- ### install from pypi

### Install from pypi

```shell
pip install DGLD
```
Expand Down Expand Up @@ -80,13 +84,13 @@ Function fit need parameters to specify number of epoch and device. For gpu, dev
```python
from DGLD.utils.evaluation import split_auc

model.fit(g, num_epoch = 5, device = 0)
result = model.predict(g, auc_test_rounds = 2)
model.fit(g, num_epoch=5, device=0)
result = model.predict(g, auc_test_rounds=2)
print(split_auc(label, result))
```


## Native Datasets

The DGLD provides native graph anomaly detection datasets that widely used by existing methods.

| Dataset | nodes | edges | attributes | anomalies |
Expand All @@ -99,9 +103,8 @@ The DGLD provides native graph anomaly detection datasets that widely used by ex
| Pubmed | 19717 | 44338 | 500 | 600 |
| ogbn-arxiv | 169343 | 1166243 | 128 | 6000 |



## Implemented Results ([Sorted Results](https://zhoushengisnoob.github.io/projects/DGLD_Fronted/leaderboard.html))

| Method | Cora | Citeseer | Pubmed | BlogCatalog | Flickr | ACM | Arxiv |
|:-------------------------------------------------------------------------:|:------:|:--------:|:------:|:-----------:|:------:|:------:|:------:|
| [CoLA](https://arxiv.org/abs/2103.00113) | 0.8823 | 0.8765 | 0.9632 | 0.6488 | 0.5790 | 0.8194 | 0.8833 |
Expand All @@ -120,9 +123,10 @@ The DGLD provides native graph anomaly detection datasets that widely used by ex
| [AdONE](https://dl.acm.org/doi/abs/10.1145/3336191.3371788) | 0.9629 | 0.8935 | 0.9030 | 0.7438 | 0.7595 | - | 0.7651 |
| [GCNAE](https://arxiv.org/abs/1611.07308) | 0.7707 | 0.7696 | 0.7941 | 0.7363 | 0.7529 | - | 0.7530 |
| [MLPAE](https://dl.acm.org/doi/10.1145/2689746.2689747) | 0.7617 | 0.7538 | 0.7211 | 0.7399 | 0.7514 | - | 0.7382 |
| [SCAN](https://dl.acm.org/doi/10.1145/1281192.1281280) | 0.6508 | 0.6671 | 0.7361 | 0.4926 | 0.6498 | - | 0.6905 |
| [SCAN](https://dl.acm.org/doi/10.1145/1281192.1281280) | 0.6508 | 0.6671 | 0.7361 | 0.4926 | 0.6498 | - | 0.6905 |

## Upcoming Features

* More Graph Anomaly Detection Methods
* Edge/Community/Graph Level Anomaly Detection Tasks
* Graphical Operation Interface
1 change: 0 additions & 1 deletion doc/docstring_html/README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
# Docstrings for DGLD models
test
9 changes: 5 additions & 4 deletions example.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import sys

sys.path.append('./src')

from dgld.utils.dataset import GraphNodeAnomalyDectionDataset
Expand All @@ -11,14 +12,14 @@
import torch
import numpy as np

gnd_dataset = GraphNodeAnomalyDectionDataset("Cora", p = 15, k = 50)
gnd_dataset = GraphNodeAnomalyDectionDataset("Cora", p=15, k=50)
g = gnd_dataset[0]
label = gnd_dataset.anomaly_label
model = CoLA(in_feats=g.ndata['feat'].shape[1])
print('-' * 10)
print('Fit : ')
model.fit(g, num_epoch=5, device = 0)
model.fit(g, num_epoch=5, device=0)
print('-' * 10)
print('Predict : ')
result = model.predict(g, auc_test_rounds=2, device = 0)
print(split_auc(label, result))
result = model.predict(g, auc_test_rounds=2, device=0)
print(split_auc(label, result))
File renamed without changes
35 changes: 19 additions & 16 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,51 @@
import sys

sys.path.append('./src')

from dgld.utils.evaluation import split_auc
from dgld.utils.common import seed_everything
from dgld.utils.argparser import parse_all_args
from dgld.utils.load_data import load_data,load_custom_data, load_truth_data
from dgld.utils.inject_anomalies import inject_contextual_anomalies,inject_structural_anomalies
from dgld.utils.common_params import Q_MAP,K,P
from dgld.utils.load_data import load_data, load_custom_data, load_truth_data
from dgld.utils.inject_anomalies import inject_contextual_anomalies, inject_structural_anomalies
from dgld.utils.common_params import Q_MAP, K, P
from dgld.utils.log import Dgldlog
from dgld.models import *
import random
import os
truth_list = ['weibo','tfinance','tsocial','reddit','Amazon','Class','Disney','elliptic','Enron']
import random
import os

truth_list = ['weibo', 'tfinance', 'tsocial', 'reddit', 'Amazon', 'Class', 'Disney', 'elliptic', 'Enron']
if __name__ == "__main__":
args_dict,args = parse_all_args()
args_dict, args = parse_all_args()
data_name = args_dict['dataset']
save_path = args.save_path
exp_name = args.exp_name
log = Dgldlog(save_path,exp_name,args)
log = Dgldlog(save_path, exp_name, args)

res_list_final = []
res_list_attrb = []
res_list_struct = []

seed_list = [random.randint(0,99999) for i in range(args.runs)]
seed_list = [random.randint(0, 99999) for i in range(args.runs)]
seed_list[0] = args_dict['seed']
for runs in range(args.runs):
log.update_runs()
seed = seed_list[runs]
seed_everything(seed)
args_dict['seed'] = seed

if data_name in truth_list:
graph = load_truth_data(data_path=args.data_path,dataset_name=data_name)
graph = load_truth_data(data_path=args.data_path, dataset_name=data_name)
elif data_name == 'custom':
graph = load_custom_data(data_path=args.data_path)
else:
graph = load_data(data_name)
graph = inject_contextual_anomalies(graph=graph,k=K,p=P,q=Q_MAP[data_name],seed=seed)
graph = inject_structural_anomalies(graph=graph,p=P,q=Q_MAP[data_name],seed=seed)
graph = inject_contextual_anomalies(graph=graph, k=K, p=P, q=Q_MAP[data_name], seed=seed)
graph = inject_structural_anomalies(graph=graph, p=P, q=Q_MAP[data_name], seed=seed)

label = graph.ndata['label']

if args.model in ['DOMINANT','AnomalyDAE','ComGA','DONE','AdONE','CONAD','ALARM','ONE','GAAN','GUIDE','CoLA',
'AAGNN', 'SLGAD','ANEMONE','GCNAE','MLPAE','SCAN']:
if args.model in ['DOMINANT', 'AnomalyDAE', 'ComGA', 'DONE', 'AdONE', 'CONAD', 'ALARM', 'ONE', 'GAAN', 'GUIDE',
'CoLA', 'AAGNN', 'SLGAD', 'ANEMONE', 'GCNAE', 'MLPAE', 'SCAN']:
model = eval(f'{args.model}(**args_dict["model"])')
else:
raise ValueError(f"{args.model} is not implemented!")
Expand All @@ -55,5 +58,5 @@
res_list_struct.append(s_score)
print(args_dict)

log.save_result(res_list_final,res_list_attrb,res_list_struct,seed_list,args)
log.save_result(res_list_final, res_list_attrb, res_list_struct, seed_list, args)
os._exit(0)
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ tqdm==4.63.0
wget==3.2
tensorboard==2.8.0
protobuf==3.19.4
tabulate==0.8.10
tabulate==0.8.10
dgl==1.1.2
10 changes: 5 additions & 5 deletions scripts/autoread_args.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import os
import sys

sys.path.append('./src')
from dgld.utils.argparser import models_set_args_map

from dgld.utils.argparser import models_set_args_map
from dgld.utils.common import saveargs2json, loadargs_from_json
from copy import deepcopy

class FakeParser():

class FakeParser:
def __init__(self):
self.options = []

Expand Down Expand Up @@ -61,6 +64,3 @@ def get_choices(kwargs):

hyper = {"hyper": options}
saveargs2json(hyper, save_path+f"{_model}_{dataset}.json")



3 changes: 0 additions & 3 deletions scripts/benchmark_aagnn.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,3 @@ do
python main_aagnn.py --dataset $dataset --device 0 --seed $seed --logdir logs/$expname > logs/$expname.log 2>&1
cat logs/$expname.log
done



3 changes: 0 additions & 3 deletions scripts/benchmark_alarm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,3 @@ do
python main_alarm.py --dataset $dataset --device 0 --seed $seed --logdir logs/$expname > logs/$expname.log 2>&1
cat logs/$expname.log
done



3 changes: 0 additions & 3 deletions scripts/benchmark_anomalydae.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,3 @@ do
python main_anomalydae.py --dataset $dataset --device 0 --seed $seed --logdir logs/$expname > logs/$expname.log 2>&1
cat logs/$expname.log
done



3 changes: 0 additions & 3 deletions scripts/benchmark_comga.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,3 @@ do
python main_comga.py --dataset $dataset --device 0 --seed $seed --logdir logs/$expname > logs/$expname.log 2>&1
cat logs/$expname.log
done



3 changes: 0 additions & 3 deletions scripts/benchmark_dominant.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,3 @@ do
python main_dominant.py --dataset $dataset --device 0 --seed $seed --logdir logs/$expname > logs/$expname.log 2>&1
cat logs/$expname.log
done



2 changes: 1 addition & 1 deletion scripts/logs/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
# Save experiment logs
# Experiment Logs
9 changes: 2 additions & 7 deletions scripts/main_aagnn.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import os
import sys

current_file_name = __file__
current_dir = os.path.dirname(os.path.dirname(os.path.abspath(current_file_name))) + '/src'
sys.path.append(current_dir)
print(current_dir)

import dgld

from dgld.utils.dataset import GraphNodeAnomalyDectionDataset
from dgld.utils.evaluation import split_auc
from dgld.models.AAGNN import AAGNN_batch

from dgld.models.AAGNN import get_parse

import dgl
import torch
import numpy as np
Expand All @@ -29,8 +29,3 @@
model.fit(g, **args["fit"])
result = model.predict(g, **args["predict"])
split_auc(label, result)





3 changes: 2 additions & 1 deletion scripts/main_alarm.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import sys

current_file_name = __file__
current_dir = os.path.dirname(os.path.dirname(os.path.abspath(current_file_name))) + '/src'
sys.path.append(current_dir)
Expand All @@ -11,6 +12,7 @@
from dgld.utils.evaluation import split_auc
from dgld.utils.common import load_ACM
from dgld.utils.common import seed_everything

import dgl
import torch
import numpy as np
Expand Down Expand Up @@ -53,4 +55,3 @@
result = model.predict(g, **args["predict"])
split_auc(label, result)
print(args)

2 changes: 2 additions & 0 deletions scripts/main_anomalydae.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import sys

current_file_name = __file__
current_dir = os.path.dirname(os.path.dirname(os.path.abspath(current_file_name))) + '/src'
sys.path.append(current_dir)
Expand All @@ -11,6 +12,7 @@
from dgld.utils.evaluation import split_auc
from dgld.utils.common import load_ACM
from dgld.utils.common import seed_everything

import dgl
import torch
import numpy as np
Expand Down
3 changes: 2 additions & 1 deletion scripts/main_cola.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Author: Peng Zhang <zzhangpeng@zju.edu.cn>
# License: BSD 2 clause

import os
import sys

current_file_name = __file__
current_dir = os.path.dirname(os.path.dirname(os.path.abspath(current_file_name))) + '/src'
sys.path.append(current_dir)
Expand Down Expand Up @@ -54,4 +56,3 @@
model.fit(g, **args["fit"])
result = model.predict(g, **args["predict"])
split_auc(label, result)

1 change: 1 addition & 0 deletions scripts/main_comga.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import sys

current_file_name = __file__
current_dir = os.path.dirname(os.path.dirname(os.path.abspath(current_file_name))) + '/src'
sys.path.append(current_dir)
Expand Down
3 changes: 2 additions & 1 deletion scripts/main_conad.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import sys

current_file_name = __file__
current_dir = os.path.dirname(os.path.dirname(os.path.abspath(current_file_name))) + '/src'
sys.path.append(current_dir)
Expand Down Expand Up @@ -55,4 +56,4 @@
model = CONAD(**args["model"])
model.fit(g, **args["fit"])
result = model.predict(g, **args["predict"])
print(split_auc(label, result))
print(split_auc(label, result))
Loading

0 comments on commit 58f5cb1

Please sign in to comment.