Compare commits
No commits in common. "3c7e3fc018df2b74648ea40592d16540a62d2df4" and "ef6eb5554576341d6daf6e312bdb97bfa44286dc" have entirely different histories.
3c7e3fc018
...
ef6eb55545
7 changed files with 0 additions and 2638 deletions
|
|
@ -1,508 +0,0 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Retrieving Bluesky datasets\n",
|
||||
"\n",
|
||||
"Retrieving Bluesky datasets with the Bluesky API."
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Retrieving Bluesky credentials and anonymity encryption key from credentials file."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"with open(\".credentials\", \"r\") as file:\n",
|
||||
" for line in file:\n",
|
||||
" if 'bluesky_username' in line:\n",
|
||||
" username = line.split('bluesky_username=')[1].strip()\n",
|
||||
" break\n",
|
||||
" for line in file:\n",
|
||||
" if 'bluesky_password' in line:\n",
|
||||
" password = line.split('bluesky_password=')[1].strip()\n",
|
||||
" break"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Initializing the Bluesky API."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from atproto import Client\n",
|
||||
"\n",
|
||||
"# Initialize and log in\n",
|
||||
"client = Client()\n",
|
||||
"client.login(username, password);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Converting the retrieval start and end time period to timestamps."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from datetime import datetime, timezone, timedelta\n",
|
||||
"\n",
|
||||
"case = '...'\n",
|
||||
"\n",
|
||||
"start_date_string = '...'\n",
|
||||
"end_date_string = '...'\n",
|
||||
"\n",
|
||||
"start_timestamp = datetime.strptime(start_date_string, '%Y-%m-%d').replace(tzinfo=timezone.utc)\n",
|
||||
"end_timestamp = datetime.strptime(end_date_string, '%Y-%m-%d').replace(tzinfo=timezone.utc)\n",
|
||||
"\n",
|
||||
"iso_start_timestamp = start_timestamp.isoformat().replace('+00:00', 'Z')\n",
|
||||
"iso_end_timestamp = end_timestamp.isoformat().replace('+00:00', 'Z')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Define functions."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pandas as pd\n",
|
||||
"import numpy as np\n",
|
||||
"import re\n",
|
||||
"from tqdm import tqdm\n",
|
||||
"from more_itertools import chunked\n",
|
||||
"\n",
|
||||
"# Remove URLs, hashtags, mentions, emojis and whitespaces\n",
|
||||
"def clean_text(text):\n",
|
||||
" text = re.sub(r'http\\S+|www\\S+|https\\S+', '', text, flags=re.MULTILINE)\n",
|
||||
" text = re.sub(r'#\\S+', '', text)\n",
|
||||
" text = re.sub(r'@\\S+', '', text)\n",
|
||||
" text = re.sub(r'[^\\w\\s,]', '', text)\n",
|
||||
" text = re.sub(r'\\s+', ' ', text).strip()\n",
|
||||
" return text\n",
|
||||
"\n",
|
||||
"# Search for posts containing a specific keyword\n",
|
||||
"def get_posts_by_keyword(keyword, since, until, limit=300):\n",
|
||||
" try:\n",
|
||||
" num_posts = 0\n",
|
||||
" post_data = []\n",
|
||||
"\n",
|
||||
" progress_bar = tqdm(total=limit, desc=\"Fetching posts\")\n",
|
||||
"\n",
|
||||
" while num_posts < limit:\n",
|
||||
" \n",
|
||||
" search_results = client.app.bsky.feed.search_posts({'q': keyword, 'since': since, 'until': until, 'lang': 'en', 'limit': 100})\n",
|
||||
" posts = search_results.posts\n",
|
||||
"\n",
|
||||
" for post in posts:\n",
|
||||
" # Extract post details\n",
|
||||
" text = clean_text(post.record.text) if hasattr(post.record, 'text') else np.nan\n",
|
||||
" iso_date = post.record.created_at if hasattr(post.record, 'created_at') else np.nan\n",
|
||||
" user = post.author.handle if hasattr(post.author, 'handle') else np.nan\n",
|
||||
"\n",
|
||||
" post_id = post.uri if hasattr(post, 'uri') else np.nan\n",
|
||||
" parent_id = post.record.reply.parent.uri if hasattr(post.record, 'reply') and hasattr(post.record.reply, 'parent') else 'no_parent'\n",
|
||||
"\n",
|
||||
" # Format date-time\n",
|
||||
" if iso_date != np.nan:\n",
|
||||
" date_obj = datetime.fromisoformat(iso_date.replace('Z', '+00:00'))\n",
|
||||
" date_str = date_obj.strftime('%Y-%m-%d %H:%M:%S')\n",
|
||||
" else:\n",
|
||||
" date_str = np.nan\n",
|
||||
"\n",
|
||||
" if post_id != np.nan and user != np.nan:\n",
|
||||
" post_data.append({\n",
|
||||
" 'date': date_str,\n",
|
||||
" 'text': text,\n",
|
||||
" 'user': user,\n",
|
||||
" 'id': post_id,\n",
|
||||
" 'parentid': parent_id\n",
|
||||
" })\n",
|
||||
" else:\n",
|
||||
" continue\n",
|
||||
" \n",
|
||||
" until = iso_date\n",
|
||||
" num_posts += len(posts)\n",
|
||||
" progress_bar.update(len(posts))\n",
|
||||
" progress_bar.set_postfix_str(f'now at: {date_str}')\n",
|
||||
"\n",
|
||||
" if date_obj < (start_timestamp + timedelta(hours=1)):\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
" progress_bar.close()\n",
|
||||
" df = pd.DataFrame(post_data)\n",
|
||||
" return df\n",
|
||||
"\n",
|
||||
" except Exception as e:\n",
|
||||
" print(f\"Error fetching posts: {e}\")\n",
|
||||
" return pd.DataFrame()\n",
|
||||
"\n",
|
||||
"# Obtain posts from uri list\n",
|
||||
"def get_posts(uris):\n",
|
||||
" try:\n",
|
||||
" post_data = []\n",
|
||||
"\n",
|
||||
" progress_bar = tqdm(total=len(uris), desc=\"Fetching posts\")\n",
|
||||
"\n",
|
||||
" for uribit in list(chunked(uris,20)):\n",
|
||||
"\n",
|
||||
" search_results = client.app.bsky.feed.get_posts({'uris': uribit})\n",
|
||||
" posts = search_results.posts\n",
|
||||
"\n",
|
||||
" for post in posts: \n",
|
||||
" # Extract post details\n",
|
||||
" text = clean_text(post.record.text) if hasattr(post.record, 'text') else np.nan\n",
|
||||
" iso_date = post.record.created_at if hasattr(post.record, 'created_at') else np.nan\n",
|
||||
" user = post.author.handle if hasattr(post.author, 'handle') else np.nan\n",
|
||||
"\n",
|
||||
" post_id = post.uri if hasattr(post, 'uri') else np.nan\n",
|
||||
" parent_id = post.record.reply.parent.uri if hasattr(post.record, 'reply') and hasattr(post.record.reply, 'parent') else 'no_parent'\n",
|
||||
"\n",
|
||||
" # Format date-time\n",
|
||||
" if iso_date != np.nan:\n",
|
||||
" date_obj = datetime.fromisoformat(iso_date.replace('Z', '+00:00'))\n",
|
||||
" date_str = date_obj.strftime('%Y-%m-%d %H:%M:%S')\n",
|
||||
" else:\n",
|
||||
" date_str = np.nan\n",
|
||||
"\n",
|
||||
" if post_id != np.nan and user != np.nan:\n",
|
||||
" post_data.append({\n",
|
||||
" 'date': date_str,\n",
|
||||
" 'text': text,\n",
|
||||
" 'user': user,\n",
|
||||
" 'id': post_id,\n",
|
||||
" 'parentid': parent_id\n",
|
||||
" })\n",
|
||||
" else:\n",
|
||||
" continue\n",
|
||||
" \n",
|
||||
" progress_bar.update(len(posts))\n",
|
||||
" \n",
|
||||
" progress_bar.close()\n",
|
||||
" df = pd.DataFrame(post_data)\n",
|
||||
" return df\n",
|
||||
"\n",
|
||||
" except Exception as e:\n",
|
||||
" print(f\"Error fetching posts: {e}\")\n",
|
||||
" return pd.DataFrame()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Retrieve posts with a keyword."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"raw_df_data = get_posts_by_keyword('...', iso_start_timestamp, iso_end_timestamp, 500000)\n",
|
||||
"raw_df_data.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Retrieve absent posts."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"id_list = raw_df_data['id'].to_list()\n",
|
||||
"id_list.append('no_parent')\n",
|
||||
"\n",
|
||||
"absent_parents = raw_df_data.loc[~raw_df_data['parentid'].isin(id_list), 'parentid'].tolist()\n",
|
||||
"\n",
|
||||
"df_absent_data = get_posts(absent_parents)\n",
|
||||
"\n",
|
||||
"df_absent_data.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Combine dataframes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_data = pd.concat(raw_df_data, df_absent_data, ignore_index=True)\n",
|
||||
"\n",
|
||||
"df_data.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Drop duplicates."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_data = df_data.drop_duplicates()\n",
|
||||
"df_data.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Remove empty entries."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_data.dropna(inplace=True,subset=['text'])\n",
|
||||
"df_data.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Remove non-english entries."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langdetect import detect\n",
|
||||
"\n",
|
||||
"def is_english(text):\n",
|
||||
" try:\n",
|
||||
" return detect(text) == 'en'\n",
|
||||
" except:\n",
|
||||
" return False\n",
|
||||
" \n",
|
||||
"df_data = df_data[df_data['text'].apply(is_english)].reset_index(drop=True)\n",
|
||||
"df_data.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Exporting the dataframe to a csv dataset."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_data.to_csv(f'../datasets/{case}.csv', index=False)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Count the number of posts per user. "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"user_posts = df_data.groupby('user')['id'].count()\n",
|
||||
"user_posts.describe()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Filter on social users."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"social_users = user_posts[(user_posts >= 5) & (user_posts <= 10)].index\n",
|
||||
"df_reduced_data = df_data[df_data['user'].isin(social_users)]\n",
|
||||
"df_reduced_data.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Close reduced dataset."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"closed_df_reduced_data = df_reduced_data.copy()\n",
|
||||
"\n",
|
||||
"id_list = closed_df_reduced_data['id'].to_list()\n",
|
||||
"id_list.append('no_parent')\n",
|
||||
"\n",
|
||||
"closed_df_reduced_data.loc[~closed_df_reduced_data['parentid'].isin(id_list), 'parentid'] = 'no_parent'\n",
|
||||
"\n",
|
||||
"closed_df_reduced_data.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Close dataset."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"closed_df_data = df_data.copy()\n",
|
||||
"\n",
|
||||
"id_list = closed_df_data['id'].to_list()\n",
|
||||
"id_list.append('no_parent')\n",
|
||||
"\n",
|
||||
"closed_df_data.loc[~closed_df_data['parentid'].isin(id_list), 'parentid'] = 'no_parent'\n",
|
||||
"\n",
|
||||
"closed_df_data.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Exporting the closed reduced dataframe to a csv dataset."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"closed_df_reduced_data.to_csv(f'../datasets/{case}-social-closed.csv', index=False)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Exporting the closed dataframe to a csv dataset."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"closed_df_data.to_csv(f'../datasets/{case}-closed.csv', index=False)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.14.6"
|
||||
},
|
||||
"vscode": {
|
||||
"interpreter": {
|
||||
"hash": "8c75c0fdd1a718867cdcb84b32adcfdbeaad00b3a4e00a59385211aeed084d4c"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -1,241 +0,0 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Construct interaction graphs\n",
|
||||
"\n",
|
||||
"Constructing interaction graphs and counting the neighbour interactions for each user."
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Import the dataset and create user nodes dictionary."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pandas as pd\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"case = '...'\n",
|
||||
"casegraphs = '...'\n",
|
||||
"\n",
|
||||
"df_data = pd.read_csv(f'../datasets/{case}.csv')\n",
|
||||
"user_nodes = df_data.groupby('user')['id'].apply(list).to_dict()\n",
|
||||
"\n",
|
||||
"df_data.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Construct and export nearest-neighbour graph and count nearest-neighbours in nearest-neighbour graph."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import networkx as nx\n",
|
||||
"\n",
|
||||
"# Define undirected graph\n",
|
||||
"G = nx.Graph()\n",
|
||||
"\n",
|
||||
"# Construct nearest-neighbour graph\n",
|
||||
"for _, row in df_data.iterrows():\n",
|
||||
" G.add_node(row['id'], user=row['user'], sentiment=row['s'], text=row['text'])\n",
|
||||
" if row['parentid'] != 'no_parent':\n",
|
||||
" G.add_edge(row['id'], row['parentid'])\n",
|
||||
"\n",
|
||||
"# Export nearest-neighbour graph\n",
|
||||
"nx.write_graphml(G, f'../datasets/{casegraphs}-nn-graph.graphml')\n",
|
||||
"\n",
|
||||
"# Define nearest-neighbour interaction count dictionary\n",
|
||||
"nn_count = {}\n",
|
||||
"\n",
|
||||
"# Count nearest neighbours for each user\n",
|
||||
"for node in G.nodes(data=True):\n",
|
||||
" node_id, attributes = node\n",
|
||||
" user = attributes['user']\n",
|
||||
"\n",
|
||||
" count = len(set(G.neighbors(node_id)) - set(user_nodes[user]))\n",
|
||||
"\n",
|
||||
" if user in nn_count:\n",
|
||||
" nn_count[user] += count\n",
|
||||
" else:\n",
|
||||
" nn_count[user] = count"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Construct and export transitive-closure graph and count nearest-neighbours in transitive-closure graph."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Construct transitive-closure graph\n",
|
||||
"tc_G = nx.transitive_closure(G)\n",
|
||||
"\n",
|
||||
"# Export transitive-closure graph\n",
|
||||
"nx.write_graphml(tc_G, f'../datasets/{casegraphs}-tc-graph.graphml')\n",
|
||||
"\n",
|
||||
"# Define transitive-closure interaction count dictionary\n",
|
||||
"tc_count = {}\n",
|
||||
"\n",
|
||||
"# Count neighbours for each user\n",
|
||||
"for node in tc_G.nodes(data=True):\n",
|
||||
" node_id, attributes = node\n",
|
||||
" user = attributes['user']\n",
|
||||
"\n",
|
||||
" count = len(set(tc_G.neighbors(node_id)) - set(user_nodes[user]))\n",
|
||||
"\n",
|
||||
" if user in tc_count:\n",
|
||||
" tc_count[user] += count\n",
|
||||
" else:\n",
|
||||
" tc_count[user] = count"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Construct and export directed-transitive-closure graph and count nearest-neighbours in directed-transitive-closure graph."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Define directed graph\n",
|
||||
"dG = nx.DiGraph()\n",
|
||||
"\n",
|
||||
"# Construct nearest-neighbour directed graph\n",
|
||||
"for _, row in df_data.iterrows():\n",
|
||||
" dG.add_node(row['id'], user=row['user'], sentiment=row['s'], text=row['text'])\n",
|
||||
" if row['parentid'] != 'no_parent':\n",
|
||||
" dG.add_edge(row['id'], row['parentid'])\n",
|
||||
"\n",
|
||||
"nx.write_graphml(dG, f'../datasets/{casegraphs}-nn-dgraph.graphml')\n",
|
||||
"\n",
|
||||
"# Construct directed-transitive-closure directed graph\n",
|
||||
"dtc_dG = nx.transitive_closure(dG)\n",
|
||||
"\n",
|
||||
"# Export directed-transitive-closure directed graph\n",
|
||||
"nx.write_graphml(dtc_dG, f'../datasets/{casegraphs}-dtc-dgraph.graphml')\n",
|
||||
"\n",
|
||||
"# Convert to directed-transitive-closure undirected graph\n",
|
||||
"dtc_G = dtc_dG.to_undirected()\n",
|
||||
"\n",
|
||||
"# Export directed-transitive-closure graph\n",
|
||||
"nx.write_graphml(dtc_G, f'../datasets/{casegraphs}-dtc-graph.graphml')\n",
|
||||
"\n",
|
||||
"# Define directed-transitive-closure interaction count dictionary\n",
|
||||
"dtc_count = {}\n",
|
||||
"\n",
|
||||
"# Count neighbours for each user\n",
|
||||
"for node in dtc_G.nodes(data=True):\n",
|
||||
" node_id, attributes = node\n",
|
||||
" user = attributes['user']\n",
|
||||
"\n",
|
||||
" count = len(set(dtc_G.neighbors(node_id)) - set(user_nodes[user]))\n",
|
||||
"\n",
|
||||
" if user in dtc_count:\n",
|
||||
" dtc_count[user] += count\n",
|
||||
" else:\n",
|
||||
" dtc_count[user] = count"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Construct and export user interaction count dataset."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"user_c = df_data.groupby('user')['id'].count().to_dict()\n",
|
||||
"user_s = df_data.groupby('user')['s'].mean().to_dict()\n",
|
||||
"user_stds = df_data.groupby('user')['s'].std().to_dict()\n",
|
||||
"\n",
|
||||
"df_users = pd.DataFrame({\n",
|
||||
" 'nn-count': pd.Series(nn_count), \n",
|
||||
" 'dtc-count': pd.Series(dtc_count), \n",
|
||||
" 'tc-count': pd.Series(tc_count),\n",
|
||||
" 'mean-sentiment': pd.Series(user_s),\n",
|
||||
" 'std-sentiment': pd.Series(user_stds),\n",
|
||||
" 'post-count': pd.Series(user_c)\n",
|
||||
"})\n",
|
||||
"\n",
|
||||
"export_dataset = f'../datasets/{case}-users.csv'\n",
|
||||
"df_users.to_csv(export_dataset, index=False)\n",
|
||||
"\n",
|
||||
"df_users.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_users.describe()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.14.6"
|
||||
},
|
||||
"vscode": {
|
||||
"interpreter": {
|
||||
"hash": "8c75c0fdd1a718867cdcb84b32adcfdbeaad00b3a4e00a59385211aeed084d4c"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -1,425 +0,0 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Compare interactions graphs\n",
|
||||
"\n",
|
||||
"Inspecting interaction and comparing graphs by counting the components, determining the connectivity, clustering and various other metrics. "
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Import the graphs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import networkx as nx\n",
|
||||
"\n",
|
||||
"casename1 = '...'\n",
|
||||
"case1 = '...'\n",
|
||||
"\n",
|
||||
"casename2 = '...'\n",
|
||||
"case2 = '...'\n",
|
||||
"\n",
|
||||
"# Import the graph\n",
|
||||
"G1 = nx.read_graphml(f'../datasets/{case1}-dtc-graph.graphml')\n",
|
||||
"G2 = nx.read_graphml(f'../datasets/{case2}-dtc-graph.graphml')\n",
|
||||
"\n",
|
||||
"# Print nodes, edges and density of the graphs\n",
|
||||
"print(f'G1:\\nNodes: {G1.number_of_nodes()}\\nEdges: {G1.number_of_edges()}\\nDensity: {nx.density(G1):.5f}')\n",
|
||||
"print(f'G2:\\nNodes: {G2.number_of_nodes()}\\nEdges: {G2.number_of_edges()}\\nDensity: {nx.density(G2):.5f}')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Remove isolated nodes."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"G1.remove_nodes_from(list(nx.isolates(G1)))\n",
|
||||
"G2.remove_nodes_from(list(nx.isolates(G2)))\n",
|
||||
"\n",
|
||||
"# Print nodes, edges and density of the graphs\n",
|
||||
"print(f'G1:\\nNodes: {G1.number_of_nodes()}\\nEdges: {G1.number_of_edges()}\\nDensity: {nx.density(G1):.5f}')\n",
|
||||
"print(f'G2:\\nNodes: {G2.number_of_nodes()}\\nEdges: {G2.number_of_edges()}\\nDensity: {nx.density(G2):.5f}')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Compute average degree, connectivity, clustering and degree_assortivity. "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pandas as pd\n",
|
||||
"\n",
|
||||
"components1 = list(nx.connected_components(G1))\n",
|
||||
"\n",
|
||||
"component_metrics1 = []\n",
|
||||
"\n",
|
||||
"for component in components1:\n",
|
||||
"\n",
|
||||
" subG = G1.subgraph(component)\n",
|
||||
"\n",
|
||||
" num_nodes = subG.number_of_nodes()\n",
|
||||
" num_edges = subG.number_of_edges()\n",
|
||||
" average_degree = (2 * num_edges) / num_nodes\n",
|
||||
" connectivity = nx.node_connectivity(subG)\n",
|
||||
" clustering = nx.average_clustering(subG)\n",
|
||||
" degree_assortivity = nx.degree_assortativity_coefficient(subG)\n",
|
||||
"\n",
|
||||
" metrics = {\n",
|
||||
" 'num_nodes': num_nodes,\n",
|
||||
" 'num_edges': num_edges,\n",
|
||||
" 'average_degree': average_degree,\n",
|
||||
" 'connectivity': connectivity,\n",
|
||||
" 'clustering': clustering,\n",
|
||||
" 'degree_assortivity': degree_assortivity,\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" component_metrics1.append(metrics)\n",
|
||||
"\n",
|
||||
"df_metric1 = pd.DataFrame(component_metrics1)\n",
|
||||
"df_metric1.describe()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"components2 = list(nx.connected_components(G2))\n",
|
||||
"\n",
|
||||
"component_metrics2 = []\n",
|
||||
"\n",
|
||||
"for component in components2:\n",
|
||||
"\n",
|
||||
" subG = G2.subgraph(component)\n",
|
||||
"\n",
|
||||
" num_nodes = subG.number_of_nodes()\n",
|
||||
" num_edges = subG.number_of_edges()\n",
|
||||
" average_degree = (2 * num_edges) / num_nodes\n",
|
||||
" connectivity = nx.node_connectivity(subG)\n",
|
||||
" clustering = nx.average_clustering(subG)\n",
|
||||
" degree_assortivity = nx.degree_assortativity_coefficient(subG)\n",
|
||||
"\n",
|
||||
" metrics = {\n",
|
||||
" 'num_nodes': num_nodes,\n",
|
||||
" 'num_edges': num_edges,\n",
|
||||
" 'average_degree': average_degree,\n",
|
||||
" 'connectivity': connectivity,\n",
|
||||
" 'clustering': clustering,\n",
|
||||
" 'degree_assortivity': degree_assortivity,\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" component_metrics2.append(metrics)\n",
|
||||
"\n",
|
||||
"df_metric2 = pd.DataFrame(component_metrics2)\n",
|
||||
"df_metric2.describe()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Filter out the outliers in the dataframe, based on number of edges."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_metric1_ro = df_metric1[(df_metric1['num_edges'] < 400) & (df_metric1['num_nodes'] > 10)]\n",
|
||||
"\n",
|
||||
"df_metric1_ro.describe()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_metric2_ro = df_metric2[(df_metric2['num_edges'] < 400) & (df_metric2['num_nodes'] > 10)]\n",
|
||||
"\n",
|
||||
"df_metric2_ro.describe()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Plot the distributions of average degree."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import seaborn as sns\n",
|
||||
"import numpy as np\n",
|
||||
"\n",
|
||||
"plt.figure(figsize=(8, 6))\n",
|
||||
"\n",
|
||||
"upper_limit = 1e3\n",
|
||||
"\n",
|
||||
"# Define the number of bins\n",
|
||||
"num_bins = 20\n",
|
||||
"\n",
|
||||
"# Calculate the combined range for both datasets\n",
|
||||
"min_value = min(df_metric1_ro['average_degree'].min(), df_metric2_ro['average_degree'].min())\n",
|
||||
"max_value = max(df_metric1_ro['average_degree'].max(), df_metric2_ro['average_degree'].max())\n",
|
||||
"\n",
|
||||
"# Create bin edges\n",
|
||||
"bins = np.linspace(min_value, max_value, num_bins + 1)\n",
|
||||
"\n",
|
||||
"# Create a single plot\n",
|
||||
"sns.histplot(df_metric1_ro['average_degree'], bins=bins, color='blue', alpha=0.5, label=f'{casename1.title()} case')\n",
|
||||
"sns.histplot(df_metric2_ro['average_degree'], bins=bins, color='orange', alpha=0.5, label=f'{casename2.title()} case')\n",
|
||||
"\n",
|
||||
"# Set y-axis to logarithmic scale\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"\n",
|
||||
"# Set titles and labels\n",
|
||||
"plt.title('Distribution of average degree (nodes > 10, edges < 400)', fontsize=16)\n",
|
||||
"plt.xlabel('Average degree')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in', top=True, right=True)\n",
|
||||
"\n",
|
||||
"# Add a legend\n",
|
||||
"plt.legend()\n",
|
||||
"\n",
|
||||
"# Show the plot\n",
|
||||
"plt.tight_layout(rect=[0, 0, 1, 0.99])\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Plot the distributions of connectivity."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import seaborn as sns\n",
|
||||
"import numpy as np\n",
|
||||
"\n",
|
||||
"plt.figure(figsize=(8, 6))\n",
|
||||
"\n",
|
||||
"upper_limit = 1e3\n",
|
||||
"\n",
|
||||
"# Define the number of bins\n",
|
||||
"num_bins = 20\n",
|
||||
"\n",
|
||||
"# Calculate the combined range for both datasets\n",
|
||||
"min_value = min(df_metric1_ro['connectivity'].min(), df_metric2_ro['connectivity'].min())\n",
|
||||
"max_value = max(df_metric1_ro['connectivity'].max(), df_metric2_ro['connectivity'].max())\n",
|
||||
"\n",
|
||||
"# Create bin edges\n",
|
||||
"bins = np.linspace(min_value, max_value, num_bins + 1)\n",
|
||||
"\n",
|
||||
"# Create a single plot\n",
|
||||
"sns.histplot(df_metric1_ro['connectivity'], bins=bins, color='blue', alpha=0.5, label=f'{casename1.title()} case')\n",
|
||||
"sns.histplot(df_metric2_ro['connectivity'], bins=bins, color='orange', alpha=0.5, label=f'{casename2.title()} case')\n",
|
||||
"\n",
|
||||
"# Set y-axis to logarithmic scale\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"\n",
|
||||
"# Set titles and labels\n",
|
||||
"plt.title('Distribution of connectivity (nodes > 10, edges < 400)', fontsize=16)\n",
|
||||
"plt.xlabel('Connectivity')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in', top=True, right=True)\n",
|
||||
"\n",
|
||||
"# Add a legend\n",
|
||||
"plt.legend()\n",
|
||||
"\n",
|
||||
"# Show the plot\n",
|
||||
"plt.tight_layout(rect=[0, 0, 1, 0.99])\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Plot the distributions of clustering."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import seaborn as sns\n",
|
||||
"import numpy as np\n",
|
||||
"\n",
|
||||
"plt.figure(figsize=(8, 6))\n",
|
||||
"\n",
|
||||
"upper_limit = 1e3\n",
|
||||
"\n",
|
||||
"# Define the number of bins\n",
|
||||
"num_bins = 20\n",
|
||||
"\n",
|
||||
"# Calculate the combined range for both datasets\n",
|
||||
"min_value = min(df_metric1_ro['clustering'].min(), df_metric2_ro['clustering'].min())\n",
|
||||
"max_value = max(df_metric1_ro['clustering'].max(), df_metric2_ro['clustering'].max())\n",
|
||||
"\n",
|
||||
"# Create bin edges\n",
|
||||
"bins = np.linspace(min_value, max_value, num_bins + 1)\n",
|
||||
"\n",
|
||||
"# Create a single plot\n",
|
||||
"sns.histplot(df_metric1_ro['clustering'], bins=bins, color='blue', alpha=0.5, label=f'{casename1.title()} case')\n",
|
||||
"sns.histplot(df_metric2_ro['clustering'], bins=bins, color='orange', alpha=0.5, label=f'{casename2.title()} case')\n",
|
||||
"\n",
|
||||
"# Set y-axis to logarithmic scale\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"\n",
|
||||
"# Set titles and labels\n",
|
||||
"plt.title('Distribution of clustering (nodes > 10, edges < 400)', fontsize=16)\n",
|
||||
"plt.xlabel('Clustering')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in', top=True, right=True)\n",
|
||||
"\n",
|
||||
"# Add a legend\n",
|
||||
"plt.legend()\n",
|
||||
"\n",
|
||||
"# Show the plot\n",
|
||||
"plt.tight_layout(rect=[0, 0, 1, 0.99])\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Plot the distributions of degree assortivity."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import seaborn as sns\n",
|
||||
"import numpy as np\n",
|
||||
"\n",
|
||||
"plt.figure(figsize=(8, 6))\n",
|
||||
"\n",
|
||||
"upper_limit = 1e3\n",
|
||||
"\n",
|
||||
"# Define the number of bins\n",
|
||||
"num_bins = 20\n",
|
||||
"\n",
|
||||
"# Calculate the combined range for both datasets\n",
|
||||
"min_value = min(df_metric1_ro['degree_assortivity'].min(), df_metric2_ro['degree_assortivity'].min())\n",
|
||||
"max_value = max(df_metric1_ro['degree_assortivity'].max(), df_metric2_ro['degree_assortivity'].max())\n",
|
||||
"\n",
|
||||
"# Create bin edges\n",
|
||||
"bins = np.linspace(min_value, max_value, num_bins + 1)\n",
|
||||
"\n",
|
||||
"# Create a single plot\n",
|
||||
"sns.histplot(df_metric1_ro['degree_assortivity'], bins=bins, color='blue', alpha=0.5, label=f'{casename1.title()} case')\n",
|
||||
"sns.histplot(df_metric2_ro['degree_assortivity'], bins=bins, color='orange', alpha=0.5, label=f'{casename2.title()} case')\n",
|
||||
"\n",
|
||||
"# Set y-axis to logarithmic scale\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"\n",
|
||||
"# Set titles and labels\n",
|
||||
"plt.title('Distribution of degree assortivity (nodes > 10, edges < 400)', fontsize=16)\n",
|
||||
"plt.xlabel('Degree assortivity')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in', top=True, right=True)\n",
|
||||
"\n",
|
||||
"# Add a legend\n",
|
||||
"plt.legend()\n",
|
||||
"\n",
|
||||
"# Show the plot\n",
|
||||
"plt.tight_layout(rect=[0, 0, 1, 0.99])\n",
|
||||
"plt.show()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.14.6"
|
||||
},
|
||||
"vscode": {
|
||||
"interpreter": {
|
||||
"hash": "8c75c0fdd1a718867cdcb84b32adcfdbeaad00b3a4e00a59385211aeed084d4c"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -1,335 +0,0 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Inspect user interactions\n",
|
||||
"\n",
|
||||
"Inspecting the user interactions obtained from the NN, DTC and TC graphs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Import the dataset."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pandas as pd\n",
|
||||
"\n",
|
||||
"casename = '...'\n",
|
||||
"case = '...'\n",
|
||||
"\n",
|
||||
"df_data = pd.read_csv(f'../datasets/{case}-closed-s-users.csv')\n",
|
||||
"\n",
|
||||
"df_data.describe()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Plot the distributions."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import seaborn as sns\n",
|
||||
"\n",
|
||||
"plt.figure(figsize=(15, 10))\n",
|
||||
"\n",
|
||||
"plt.subplot(2,3,1)\n",
|
||||
"sns.histplot(df_data['nn-count'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.title('Distribution of NN interactions')\n",
|
||||
"plt.xlabel('NN interactions')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(2,3,2)\n",
|
||||
"sns.histplot(df_data['dtc-count'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.title('Distribution of DTC interactions')\n",
|
||||
"plt.xlabel('DTC interactions')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(2,3,3)\n",
|
||||
"sns.histplot(df_data['tc-count'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.title('Distribution of TC interactions')\n",
|
||||
"plt.xlabel('TC interactions')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(2,3,4)\n",
|
||||
"sns.histplot(df_data['post-count'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.title('Distribution of posts')\n",
|
||||
"plt.xlabel('Number of posts')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(2,3,5)\n",
|
||||
"sns.histplot(df_data['mean-sentiment'], bins=20, kde=True)\n",
|
||||
"plt.title('Distribution of mean sentiment')\n",
|
||||
"plt.xlabel('Mean sentiment')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(2,3,6)\n",
|
||||
"sns.histplot(df_data['std-sentiment'], bins=20, kde=True)\n",
|
||||
"plt.title('Distribution of SD sentiment')\n",
|
||||
"plt.xlabel('SD sentiment')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.suptitle(f'Distribution of user metrics {casename} case', fontsize=16)\n",
|
||||
"plt.tight_layout(rect=[0, 0, 1, 0.99])\n",
|
||||
"\n",
|
||||
"plt.savefig(f'../datasets/{case}-user-metrics.png')\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Plot interaction count against mean sentiment, SD sentiment and post count."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pandas as pd\n",
|
||||
"import seaborn as sns\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"\n",
|
||||
"# Define the pairs of variables for the subplots\n",
|
||||
"variables = [\n",
|
||||
" (\"nn-count\", \"mean-sentiment\"),\n",
|
||||
" (\"dtc-count\", \"mean-sentiment\"),\n",
|
||||
" (\"tc-count\", \"mean-sentiment\"),\n",
|
||||
" (\"nn-count\", \"std-sentiment\"),\n",
|
||||
" (\"dtc-count\", \"std-sentiment\"),\n",
|
||||
" (\"tc-count\", \"std-sentiment\"),\n",
|
||||
" (\"nn-count\", \"post-count\"),\n",
|
||||
" (\"dtc-count\", \"post-count\"),\n",
|
||||
" (\"tc-count\", \"post-count\"),\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# Create the figure\n",
|
||||
"plt.figure(figsize=(15, 15))\n",
|
||||
"\n",
|
||||
"# Loop through the variables and create subplots\n",
|
||||
"for i, (x_var, y_var) in enumerate(variables):\n",
|
||||
" plt.subplot(3, 3, i + 1)\n",
|
||||
" \n",
|
||||
" # Drop NaN values for the current pair of variables\n",
|
||||
" df_nonan = df_data.dropna(subset=[x_var, y_var])\n",
|
||||
" \n",
|
||||
" # Create scatter plot\n",
|
||||
" sns.scatterplot(x=x_var, y=y_var, data=df_nonan, alpha=0.4, color=\"black\", edgecolor=None)\n",
|
||||
" \n",
|
||||
" # Create Lowess regression plot\n",
|
||||
" sns.regplot(x=x_var, y=y_var, data=df_nonan, scatter=False, lowess=True, line_kws={'color': 'blue', 'linewidth': 2}, label=\"Lowess fit\")\n",
|
||||
" \n",
|
||||
" # Set logarithmic scale for x-axis\n",
|
||||
" plt.xscale(\"log\")\n",
|
||||
" \n",
|
||||
" # Set labels and grid\n",
|
||||
" plt.xlabel(x_var.replace('-', ' '))\n",
|
||||
" plt.ylabel(y_var.replace('-', ' '))\n",
|
||||
" plt.grid()\n",
|
||||
" plt.legend()\n",
|
||||
" plt.tick_params(axis='both', direction='in', top=True, right=True)\n",
|
||||
"\n",
|
||||
"# Set the overall title and layout\n",
|
||||
"plt.suptitle(f'Scatter plot of user metrics against interaction count {casename} case', fontsize=16)\n",
|
||||
"plt.tight_layout(rect=[0, 0, 1, 0.99])\n",
|
||||
"\n",
|
||||
"# Save the figure\n",
|
||||
"plt.savefig(f'../datasets/{case}-user-interaction-scatter.png')\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Plot (simplified) interaction count against mean sentiment, SD sentiment and post count. "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pandas as pd\n",
|
||||
"import seaborn as sns\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"from scipy import stats\n",
|
||||
"\n",
|
||||
"# Assuming df_data is your DataFrame and casename and case are defined\n",
|
||||
"plt.figure(figsize=(15, 15))\n",
|
||||
"\n",
|
||||
"# Define the pairs of variables for the subplots\n",
|
||||
"variables = [\n",
|
||||
" (\"nn-count\", \"mean-sentiment\"),\n",
|
||||
" (\"dtc-count\", \"mean-sentiment\"),\n",
|
||||
" (\"tc-count\", \"mean-sentiment\"),\n",
|
||||
" (\"nn-count\", \"std-sentiment\"),\n",
|
||||
" (\"dtc-count\", \"std-sentiment\"),\n",
|
||||
" (\"tc-count\", \"std-sentiment\"),\n",
|
||||
" (\"nn-count\", \"post-count\"),\n",
|
||||
" (\"dtc-count\", \"post-count\"),\n",
|
||||
" (\"tc-count\", \"post-count\"),\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# Loop through the variables and create subplots\n",
|
||||
"for i, (x_var, y_var) in enumerate(variables):\n",
|
||||
" plt.subplot(3, 3, i + 1)\n",
|
||||
" \n",
|
||||
" # Drop NaN values for the current pair of variables\n",
|
||||
" df_nonan = df_data.dropna(subset=[x_var, y_var])\n",
|
||||
" \n",
|
||||
" # Create the regression plot\n",
|
||||
" sns.regplot(x=x_var, y=y_var, data=df_nonan, scatter=False, ci=68, line_kws={'color': 'blue', 'linewidth': 2})\n",
|
||||
" \n",
|
||||
" # Fit the regression model and get r and p values\n",
|
||||
" slope, intercept, r_value, p_value, std_err = stats.linregress(df_nonan[x_var], df_nonan[y_var])\n",
|
||||
" \n",
|
||||
" # Add labels and grid\n",
|
||||
" plt.xlabel(x_var.replace('-', ' '))\n",
|
||||
" plt.ylabel(y_var.replace('-', ' '))\n",
|
||||
" plt.grid()\n",
|
||||
" plt.tick_params(axis='both', direction='in', top=True, right=True)\n",
|
||||
" \n",
|
||||
" # Add text annotation for r and p values\n",
|
||||
" plt.text(0.05, 0.95, f'r = {r_value:.4f}\\np = {max(p_value, 0.0001):.4f}', transform=plt.gca().transAxes, fontsize=12, verticalalignment='top', bbox=dict(facecolor='white', alpha=0.5))\n",
|
||||
"\n",
|
||||
"# Set the overall title and layout\n",
|
||||
"plt.suptitle(f'Regression plot of user metrics against interaction count {casename} case', fontsize=16)\n",
|
||||
"plt.tight_layout(rect=[0, 0, 1, 0.99])\n",
|
||||
"\n",
|
||||
"# Save the figure\n",
|
||||
"plt.savefig(f'../datasets/{case}-user-interaction-regression.png')\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Take out change in sentiment regressions."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pandas as pd\n",
|
||||
"import seaborn as sns\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"from scipy import stats\n",
|
||||
"\n",
|
||||
"# Assuming df_data is your DataFrame and casename and case are defined\n",
|
||||
"fig, axes = plt.subplots(1, 3, figsize=(15, 6), sharey=True)\n",
|
||||
"\n",
|
||||
"# Define the variables for std-sentiment plots\n",
|
||||
"variables = [\n",
|
||||
" (\"nn-count\", \"std-sentiment\"),\n",
|
||||
" (\"dtc-count\", \"std-sentiment\"),\n",
|
||||
" (\"tc-count\", \"std-sentiment\"),\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# Loop through the variables and create subplots\n",
|
||||
"for i, (ax, (x_var, y_var)) in enumerate(zip(axes, variables)):\n",
|
||||
" # Drop NaN values for the current pair of variables\n",
|
||||
" df_nonan = df_data.dropna(subset=[x_var, y_var])\n",
|
||||
" \n",
|
||||
" # Create the regression plot\n",
|
||||
" sns.regplot(x=x_var, y=y_var, data=df_nonan, scatter=False, ci=68, line_kws={'color': 'blue', 'linewidth': 2}, ax=ax)\n",
|
||||
" \n",
|
||||
" # Fit the regression model and get r and p values\n",
|
||||
" slope, intercept, r_value, p_value, std_err = stats.linregress(df_nonan[x_var], df_nonan[y_var])\n",
|
||||
" \n",
|
||||
" # Add labels and grid\n",
|
||||
" ax.set_xlabel(x_var.replace('-', ' '))\n",
|
||||
" if i == 0:\n",
|
||||
" ax.set_ylabel(y_var.replace('-', ' '))\n",
|
||||
" else:\n",
|
||||
" ax.set_ylabel('')\n",
|
||||
" ax.grid()\n",
|
||||
" ax.tick_params(axis='both', direction='in', top=True, right=True)\n",
|
||||
" \n",
|
||||
" # Add text annotation for r and p values\n",
|
||||
" ax.text(0.05, 0.95, f'r = {r_value:.4f}\\np = {max(p_value, 0.0001):.4f}', transform=ax.transAxes, fontsize=12, verticalalignment='top', bbox=dict(facecolor='white', alpha=0.5))\n",
|
||||
"\n",
|
||||
"# Set the overall title and layout\n",
|
||||
"plt.suptitle(f'Regression plot of standard deviation of sentiment against interaction count {casename} case', fontsize=16)\n",
|
||||
"plt.tight_layout(rect=[0, 0, 1, 0.95])\n",
|
||||
"\n",
|
||||
"# Save the figure\n",
|
||||
"plt.savefig(f'../datasets/{case}-user-std-sentiment-regression.png')\n",
|
||||
"plt.show()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.14.6"
|
||||
},
|
||||
"vscode": {
|
||||
"interpreter": {
|
||||
"hash": "8c75c0fdd1a718867cdcb84b32adcfdbeaad00b3a4e00a59385211aeed084d4c"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -1,671 +0,0 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Inspect interaction graphs\n",
|
||||
"\n",
|
||||
"Inspecting interaction graphs by counting the components, determining the connectivity, clustering and various other metrics. "
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Import the graph."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import networkx as nx\n",
|
||||
"\n",
|
||||
"casename = '...'\n",
|
||||
"case = '...'\n",
|
||||
"\n",
|
||||
"# Import the graph\n",
|
||||
"G = nx.read_graphml(f'../datasets/{case}-dtc-graph.graphml')\n",
|
||||
"\n",
|
||||
"# Print nodes, edges and density of the graph\n",
|
||||
"print(f'Nodes: {G.number_of_nodes()}\\nEdges: {G.number_of_edges()}\\nDensity: {nx.density(G):.5f}')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Remove isolated nodes."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"G.remove_nodes_from(list(nx.isolates(G)))\n",
|
||||
"print(f'Nodes: {G.number_of_nodes()}\\nEdges: {G.number_of_edges()}\\nDensity: {nx.density(G):.5f}')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Compute number of connected components."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"nx.number_connected_components(G)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Compute metrics of each component."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pandas as pd\n",
|
||||
"\n",
|
||||
"components = list(nx.connected_components(G))\n",
|
||||
"\n",
|
||||
"component_metrics = []\n",
|
||||
"\n",
|
||||
"for component in components:\n",
|
||||
"\n",
|
||||
" subG = G.subgraph(component)\n",
|
||||
"\n",
|
||||
" num_nodes = subG.number_of_nodes()\n",
|
||||
" num_edges = subG.number_of_edges()\n",
|
||||
" diameter = nx.diameter(subG)\n",
|
||||
" average_degree = (2 * num_edges) / num_nodes\n",
|
||||
" density = nx.density(subG)\n",
|
||||
" connectivity = nx.node_connectivity(subG)\n",
|
||||
" clustering = nx.average_clustering(subG)\n",
|
||||
" degree_assortivity = nx.degree_assortativity_coefficient(subG)\n",
|
||||
" sentiment_assortivity = nx.numeric_assortativity_coefficient(subG, 'sentiment')\n",
|
||||
"\n",
|
||||
" metrics = {\n",
|
||||
" 'num_nodes': num_nodes,\n",
|
||||
" 'num_edges': num_edges,\n",
|
||||
" 'diameter': diameter,\n",
|
||||
" 'average_degree': average_degree,\n",
|
||||
" 'density': density,\n",
|
||||
" 'connectivity': connectivity,\n",
|
||||
" 'clustering': clustering,\n",
|
||||
" 'degree_assortivity': degree_assortivity,\n",
|
||||
" 'sentiment_assortivity': sentiment_assortivity\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" component_metrics.append(metrics)\n",
|
||||
"\n",
|
||||
"df_metric = pd.DataFrame(component_metrics)\n",
|
||||
"df_metric.describe()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Plot the distribution of the metrics."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import seaborn as sns\n",
|
||||
"\n",
|
||||
"plt.figure(figsize=(15, 15))\n",
|
||||
"\n",
|
||||
"upper_limit = 1e5\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 1)\n",
|
||||
"sns.histplot(df_metric['num_nodes'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of nodes')\n",
|
||||
"plt.xlabel('Number of nodes')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 2)\n",
|
||||
"sns.histplot(df_metric['num_edges'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of edges')\n",
|
||||
"plt.xlabel('Number of edges')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 3)\n",
|
||||
"sns.histplot(df_metric['diameter'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of diameter')\n",
|
||||
"plt.xlabel('Diameter')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 4)\n",
|
||||
"sns.histplot(df_metric['average_degree'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of average degree')\n",
|
||||
"plt.xlabel('Average degree')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 5)\n",
|
||||
"sns.histplot(df_metric['density'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(1e1, upper_limit)\n",
|
||||
"plt.title('Distribution of density')\n",
|
||||
"plt.xlabel('Density')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 6)\n",
|
||||
"sns.histplot(df_metric['connectivity'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of connectivity')\n",
|
||||
"plt.xlabel('Connectivity')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 7)\n",
|
||||
"sns.histplot(df_metric['clustering'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of clustering')\n",
|
||||
"plt.xlabel('Clustering')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 8)\n",
|
||||
"sns.histplot(df_metric['degree_assortivity'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of degree assortivity')\n",
|
||||
"plt.xlabel('Degree assortivity')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 9)\n",
|
||||
"sns.histplot(df_metric['sentiment_assortivity'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of sentiment assortivity')\n",
|
||||
"plt.xlabel('Sentiment assortivity')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.suptitle(f'Metrics {casename} case', fontsize=16)\n",
|
||||
"plt.tight_layout(rect=[0, 0, 1, 0.99])\n",
|
||||
"\n",
|
||||
"plt.savefig(f'../datasets/{case}-metrics.png')\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Filter out the outliers in the dataframe, based on number of edges."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_metric_ro = df_metric[df_metric['num_edges'] < 400]\n",
|
||||
"\n",
|
||||
"df_metric_ro.describe()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Plot the distribution of the metrics of the outlier filtered dataframe."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Set up the matplotlib figure\n",
|
||||
"plt.figure(figsize=(15, 15))\n",
|
||||
"\n",
|
||||
"upper_limit = 1e5\n",
|
||||
"\n",
|
||||
"# Plot distributions\n",
|
||||
"plt.subplot(3, 3, 1)\n",
|
||||
"sns.histplot(df_metric_ro['num_nodes'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of nodes')\n",
|
||||
"plt.xlabel('Number of nodes')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 2)\n",
|
||||
"sns.histplot(df_metric_ro['num_edges'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of edges')\n",
|
||||
"plt.xlabel('Number of edges')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 3)\n",
|
||||
"sns.histplot(df_metric_ro['diameter'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of diameter')\n",
|
||||
"plt.xlabel('Diameter')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 4)\n",
|
||||
"sns.histplot(df_metric_ro['average_degree'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of average degree')\n",
|
||||
"plt.xlabel('Average degree')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 5)\n",
|
||||
"sns.histplot(df_metric_ro['density'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(1e1, upper_limit)\n",
|
||||
"plt.title('Distribution of density')\n",
|
||||
"plt.xlabel('Density')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 6)\n",
|
||||
"sns.histplot(df_metric_ro['connectivity'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of connectivity')\n",
|
||||
"plt.xlabel('Connectivity')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 7)\n",
|
||||
"sns.histplot(df_metric_ro['clustering'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of clustering')\n",
|
||||
"plt.xlabel('Clustering')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 8)\n",
|
||||
"sns.histplot(df_metric_ro['degree_assortivity'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of degree assortivity')\n",
|
||||
"plt.xlabel('Degree assortivity')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 9)\n",
|
||||
"sns.histplot(df_metric_ro['sentiment_assortivity'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of sentiment assortivity')\n",
|
||||
"plt.xlabel('Sentiment assortivity')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.suptitle(f'Metrics (edges < 400) {casename} case', fontsize=16)\n",
|
||||
"plt.tight_layout(rect=[0, 0, 1, 0.99])\n",
|
||||
"\n",
|
||||
"plt.savefig(f'../datasets/{case}-metrics-ro.png')\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Filter metrics on number of nodes."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_metric_ls = df_metric[df_metric['num_nodes'] > 10]\n",
|
||||
"\n",
|
||||
"df_metric_ls.describe()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Plot the distribution of the metrics of the large structures set."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Set up the matplotlib figure\n",
|
||||
"plt.figure(figsize=(15, 15))\n",
|
||||
"\n",
|
||||
"upper_limit = 1e3\n",
|
||||
"\n",
|
||||
"# Plot distributions\n",
|
||||
"plt.subplot(3, 3, 1)\n",
|
||||
"sns.histplot(df_metric_ls['num_nodes'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of nodes')\n",
|
||||
"plt.xlabel('Number of nodes')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 2)\n",
|
||||
"sns.histplot(df_metric_ls['num_edges'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of edges')\n",
|
||||
"plt.xlabel('Number of edges')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 3)\n",
|
||||
"sns.histplot(df_metric_ls['diameter'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of diameter')\n",
|
||||
"plt.xlabel('Diameter')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 4)\n",
|
||||
"sns.histplot(df_metric_ls['average_degree'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of average degree')\n",
|
||||
"plt.xlabel('Average degree')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 5)\n",
|
||||
"sns.histplot(df_metric_ls['density'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(1e1, upper_limit)\n",
|
||||
"plt.title('Distribution of density')\n",
|
||||
"plt.xlabel('Density')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 6)\n",
|
||||
"sns.histplot(df_metric_ls['connectivity'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of connectivity')\n",
|
||||
"plt.xlabel('Connectivity')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 7)\n",
|
||||
"sns.histplot(df_metric_ls['clustering'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of clustering')\n",
|
||||
"plt.xlabel('Clustering')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 8)\n",
|
||||
"sns.histplot(df_metric_ls['degree_assortivity'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of degree assortivity')\n",
|
||||
"plt.xlabel('Degree assortivity')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 9)\n",
|
||||
"sns.histplot(df_metric_ls['sentiment_assortivity'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of sentiment assortivity')\n",
|
||||
"plt.xlabel('Sentiment assortivity')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.suptitle(f'Metrics (nodes > 10) {casename} case', fontsize=16)\n",
|
||||
"plt.tight_layout(rect=[0, 0, 1, 0.99])\n",
|
||||
"\n",
|
||||
"plt.savefig(f'../datasets/{case}-metrics-ls.png')\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Filter out the outliers in the large structures dataset, based on number of edges."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_metric_ls_ro = df_metric_ls[df_metric_ls['num_edges'] < 400]\n",
|
||||
"\n",
|
||||
"df_metric_ls_ro.describe()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Set up the matplotlib figure\n",
|
||||
"plt.figure(figsize=(15, 15))\n",
|
||||
"\n",
|
||||
"upper_limit = 1e3\n",
|
||||
"\n",
|
||||
"# Plot distributions\n",
|
||||
"plt.subplot(3, 3, 1)\n",
|
||||
"sns.histplot(df_metric_ls_ro['num_nodes'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of nodes')\n",
|
||||
"plt.xlabel('Number of nodes')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 2)\n",
|
||||
"sns.histplot(df_metric_ls_ro['num_edges'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of edges')\n",
|
||||
"plt.xlabel('Number of edges')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 3)\n",
|
||||
"sns.histplot(df_metric_ls_ro['diameter'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of diameter')\n",
|
||||
"plt.xlabel('Diameter')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 4)\n",
|
||||
"sns.histplot(df_metric_ls_ro['average_degree'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of average degree')\n",
|
||||
"plt.xlabel('Average degree')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 5)\n",
|
||||
"sns.histplot(df_metric_ls_ro['density'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(1e1, upper_limit)\n",
|
||||
"plt.title('Distribution of density')\n",
|
||||
"plt.xlabel('Density')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 6)\n",
|
||||
"sns.histplot(df_metric_ls_ro['connectivity'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of connectivity')\n",
|
||||
"plt.xlabel('Connectivity')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 7)\n",
|
||||
"sns.histplot(df_metric_ls_ro['clustering'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of clustering')\n",
|
||||
"plt.xlabel('Clustering')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 8)\n",
|
||||
"sns.histplot(df_metric_ls_ro['degree_assortivity'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of degree assortivity')\n",
|
||||
"plt.xlabel('Degree assortivity')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.subplot(3, 3, 9)\n",
|
||||
"sns.histplot(df_metric_ls_ro['sentiment_assortivity'], bins=20)\n",
|
||||
"plt.yscale('log')\n",
|
||||
"plt.ylim(0.9, upper_limit)\n",
|
||||
"plt.title('Distribution of sentiment assortivity')\n",
|
||||
"plt.xlabel('Sentiment assortivity')\n",
|
||||
"plt.ylabel('Count')\n",
|
||||
"plt.grid()\n",
|
||||
"plt.tick_params(axis='both', direction='in',top=True, right=True)\n",
|
||||
"\n",
|
||||
"plt.suptitle(f'Metrics (nodes > 10, edges < 400) {casename} case', fontsize=16)\n",
|
||||
"plt.tight_layout(rect=[0, 0, 1, 0.99])\n",
|
||||
"\n",
|
||||
"plt.savefig(f'../datasets/{case}-metrics-ls-ro.png')\n",
|
||||
"plt.show()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.14.6"
|
||||
},
|
||||
"vscode": {
|
||||
"interpreter": {
|
||||
"hash": "8c75c0fdd1a718867cdcb84b32adcfdbeaad00b3a4e00a59385211aeed084d4c"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
import os
|
||||
import pandas as pd
|
||||
import torch
|
||||
from transformers import DistilBertTokenizerFast
|
||||
from torch.utils.data import DataLoader
|
||||
from transformers import DistilBertForSequenceClassification
|
||||
from tqdm import tqdm
|
||||
|
||||
# Importing the csv dataset.
|
||||
case = '...'
|
||||
df_data = pd.read_csv(f'../datasets/{case}.csv')
|
||||
print(len(df_data))
|
||||
|
||||
# Preparing the dataset for the network this includes tokenization, encoding and creating dataloaders.
|
||||
model_name = 'distilbert-base-uncased'
|
||||
tokenizer = DistilBertTokenizerFast.from_pretrained(model_name)
|
||||
|
||||
encodings = tokenizer(df_data['text'].tolist(), truncation=True, padding=True, return_tensors='pt')
|
||||
|
||||
dataset = torch.utils.data.TensorDataset(
|
||||
encodings['input_ids'],
|
||||
encodings['attention_mask']
|
||||
)
|
||||
dataloader = DataLoader(dataset, batch_size=45, shuffle=False)
|
||||
|
||||
# Loading the model.
|
||||
model= torch.load('models/bert-aclimdb.pth')
|
||||
|
||||
# Using the model to perform sentiment analysis on the dataset.
|
||||
model.eval()
|
||||
list_predicted_scores = []
|
||||
|
||||
for batch in tqdm(dataloader):
|
||||
with torch.no_grad():
|
||||
input_ids, attention_mask = batch
|
||||
|
||||
# Obtaining the sentiment score.
|
||||
output = model(input_ids=input_ids, attention_mask=attention_mask)
|
||||
predicted_scores = output.logits.view(-1)
|
||||
|
||||
# Writing the sentiment score to the list.
|
||||
list_predicted_scores.extend(predicted_scores.tolist())
|
||||
|
||||
# Inserting the sentiment score in the dataset.
|
||||
df_data['s'] = list_predicted_scores
|
||||
|
||||
# Exporting the dataframe to a csv dataset.
|
||||
df_data.to_csv(f'../datasets/{case}-s.csv', index=False)
|
||||
|
|
@ -1,410 +0,0 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Sentiment analysis with BERT\n",
|
||||
"\n",
|
||||
"Using transformers with the distilled bert-base model on the IMDB dataset, to perform continuous score sentiment analysis."
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Retrieving IMDB training and testing dataset from datasets directory."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"import pandas as pd\n",
|
||||
"\n",
|
||||
"imdb_train_dataset = \"aclimdb/train\"\n",
|
||||
"imdb_test_dataset = \"aclimdb/test\"\n",
|
||||
"\n",
|
||||
"train_reviews = []\n",
|
||||
"train_scores = []\n",
|
||||
"test_reviews = []\n",
|
||||
"test_scores = []\n",
|
||||
"\n",
|
||||
"for dataset, reviews, scores in [(imdb_train_dataset, train_reviews, train_scores), (imdb_test_dataset, test_reviews, test_scores)]:\n",
|
||||
" for sentiment in ['pos','neg']:\n",
|
||||
" sentiment_dir = os.path.join(dataset,sentiment)\n",
|
||||
"\n",
|
||||
" for filename in os.listdir(sentiment_dir):\n",
|
||||
" if filename.endswith('.txt'):\n",
|
||||
" with open(os.path.join(sentiment_dir,filename),'r',encoding='utf-8') as file:\n",
|
||||
" review = file.read()\n",
|
||||
" sentiment_score = int(filename[:-4].split('_')[1])\n",
|
||||
"\n",
|
||||
" scores.append(sentiment_score)\n",
|
||||
" reviews.append(review)\n",
|
||||
"\n",
|
||||
"df_train = pd.DataFrame({'text': train_reviews, 'sentiment': train_scores})\n",
|
||||
"df_test = pd.DataFrame({'text': test_reviews, 'sentiment': test_scores}).sample(5000)\n",
|
||||
"\n",
|
||||
"df_train.info()\n",
|
||||
"print('')\n",
|
||||
"df_test.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Normalizing the training and testing dataset to a range of -1 to 1."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def normalize(n):\n",
|
||||
" normal_n = (n - 5) / 5\n",
|
||||
" return normal_n\n",
|
||||
"\n",
|
||||
"df_train['s'] = normalize(df_train['sentiment'])\n",
|
||||
"df_test['s'] = normalize(df_test['sentiment'])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Evaluating the summary statistics of the training and testing dataset."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_train['s'].describe()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_test['s'].describe()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Determining the length of the training and testing dataset, to set a proper batch size."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"print(f\"Length training set: {len(df_train)}\\nLength testing set: {len(df_test)}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Preparing the data for BERT, this includes tokenization, encoding and creating dataloaders for both training and testing datasets."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import torch\n",
|
||||
"from transformers import DistilBertTokenizerFast\n",
|
||||
"from torch.utils.data import DataLoader\n",
|
||||
"from transformers import DistilBertForSequenceClassification\n",
|
||||
"\n",
|
||||
"model_name = \"distilbert-base-uncased\"\n",
|
||||
"tokenizer = DistilBertTokenizerFast.from_pretrained(model_name)\n",
|
||||
"\n",
|
||||
"# Tokenize and encode the text data\n",
|
||||
"train_encodings = tokenizer(df_train['text'].tolist(), truncation=True, padding=True, return_tensors='pt')\n",
|
||||
"test_encodings = tokenizer(df_test['text'].tolist(), truncation=True, padding=True, return_tensors='pt')\n",
|
||||
"\n",
|
||||
"# Create data loaders\n",
|
||||
"train_dataset = torch.utils.data.TensorDataset(\n",
|
||||
" train_encodings['input_ids'], \n",
|
||||
" train_encodings['attention_mask'], \n",
|
||||
" torch.tensor(df_train['s'].values, dtype=torch.float32)\n",
|
||||
")\n",
|
||||
"train_dataloader = DataLoader(train_dataset, batch_size=25, shuffle=True)\n",
|
||||
"\n",
|
||||
"test_dataset = torch.utils.data.TensorDataset(\n",
|
||||
" test_encodings['input_ids'], \n",
|
||||
" test_encodings['attention_mask'], \n",
|
||||
" torch.tensor(df_test['s'].values, dtype=torch.float32)\n",
|
||||
")\n",
|
||||
"test_dataloader = DataLoader(test_dataset, batch_size=25, shuffle=False)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Defining the model: distilbert."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model = DistilBertForSequenceClassification.from_pretrained(model_name, num_labels=1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Defining the optimizer and loss function."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from torch.optim import AdamW\n",
|
||||
"from torch.nn import L1Loss\n",
|
||||
"\n",
|
||||
"optimizer = AdamW(model.parameters(), lr=1e-5)\n",
|
||||
"loss_fn = L1Loss()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Training loop. Here BERT will be trained with the training dataset."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from torch.utils.tensorboard import SummaryWriter\n",
|
||||
"\n",
|
||||
"log_dir = 'bert-aclimdb/logs'\n",
|
||||
"writer = SummaryWriter(log_dir)\n",
|
||||
"global_step = 0\n",
|
||||
"\n",
|
||||
"num_epochs = 30\n",
|
||||
"\n",
|
||||
"early_stop_patience = 2\n",
|
||||
"best_validation_loss = float('inf')\n",
|
||||
"no_improvement_counter = 0\n",
|
||||
"\n",
|
||||
"for epoch in range(num_epochs):\n",
|
||||
" model.train()\n",
|
||||
" total_loss = 0\n",
|
||||
" num_batches = 0\n",
|
||||
"\n",
|
||||
" for batch in train_dataloader:\n",
|
||||
" global_step += 1\n",
|
||||
" num_batches += 1\n",
|
||||
" input_ids, attention_mask, target_scores = batch\n",
|
||||
"\n",
|
||||
" # Forward pass\n",
|
||||
" output = model(input_ids=input_ids, attention_mask=attention_mask)\n",
|
||||
" predicted_scores = output.logits.view(-1)\n",
|
||||
"\n",
|
||||
" # Calculating the loss\n",
|
||||
" loss = loss_fn(predicted_scores, target_scores)\n",
|
||||
"\n",
|
||||
" # The total loss per epoch\n",
|
||||
" total_loss += loss.item()\n",
|
||||
"\n",
|
||||
" # Determining the average loss in the epoch\n",
|
||||
" average_loss = total_loss / num_batches\n",
|
||||
"\n",
|
||||
" # Tensorboard logging\n",
|
||||
" writer.add_scalar('batch-loss-train', average_loss, global_step)\n",
|
||||
"\n",
|
||||
" # Backward pass and optimization\n",
|
||||
" loss.backward()\n",
|
||||
" optimizer.step()\n",
|
||||
" optimizer.zero_grad()\n",
|
||||
"\n",
|
||||
" # Determining the average loss for the epoch\n",
|
||||
" average_loss = total_loss / len(train_dataloader)\n",
|
||||
"\n",
|
||||
" # Logging\n",
|
||||
" writer.add_scalar('epoch-loss-train', average_loss, epoch + 1)\n",
|
||||
"\n",
|
||||
" # Validation\n",
|
||||
" model.eval()\n",
|
||||
" total_loss = 0\n",
|
||||
"\n",
|
||||
" for batch in test_dataloader:\n",
|
||||
" with torch.no_grad():\n",
|
||||
" input_ids, attention_mask, target_scores = batch\n",
|
||||
"\n",
|
||||
" # Obtaining the scores\n",
|
||||
" output = model(input_ids=input_ids, attention_mask=attention_mask)\n",
|
||||
" predicted_scores = output.logits.view(-1)\n",
|
||||
"\n",
|
||||
" # Calculating the loss\n",
|
||||
" loss = loss_fn(predicted_scores, target_scores)\n",
|
||||
"\n",
|
||||
" # The total loss per epoch\n",
|
||||
" total_loss += loss.item()\n",
|
||||
"\n",
|
||||
" # Determining the average loss for the epoch\n",
|
||||
" average_loss = total_loss / len(test_dataloader)\n",
|
||||
"\n",
|
||||
" # Logging \n",
|
||||
" writer.add_scalar('epoch-loss-validation', average_loss, epoch + 1)\n",
|
||||
" print(f\"Epoch {epoch + 1}/{num_epochs}, Validation loss: {average_loss:.4f}\\n\")\n",
|
||||
"\n",
|
||||
" # Saving the model\n",
|
||||
" torch.save(model, f'bert-aclimdb/{epoch + 1}.pth')\n",
|
||||
"\n",
|
||||
" # Early stopping check\n",
|
||||
" if average_loss < best_validation_loss:\n",
|
||||
" best_validation_loss = average_loss\n",
|
||||
" no_improvement_counter = 0\n",
|
||||
" else:\n",
|
||||
" no_improvement_counter += 1\n",
|
||||
"\n",
|
||||
" if no_improvement_counter >= early_stop_patience:\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
"writer.close()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Loading a version of the model."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model = torch.load('bert-aclimdb/4.pth')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Evaluating the model, with as output the MAE, MSE and R-value."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from scipy.stats import pearsonr\n",
|
||||
"from sklearn.metrics import mean_squared_error, mean_absolute_error\n",
|
||||
"\n",
|
||||
"model.eval()\n",
|
||||
"list_predicted_scores = []\n",
|
||||
"\n",
|
||||
"for batch in test_dataloader:\n",
|
||||
" with torch.no_grad():\n",
|
||||
" input_ids, attention_mask, scores = batch\n",
|
||||
"\n",
|
||||
" # Obtaining the scores\n",
|
||||
" output = model(input_ids=input_ids, attention_mask=attention_mask)\n",
|
||||
" predicted_scores = output.logits.view(-1)\n",
|
||||
"\n",
|
||||
" # Writing the scores to the list\n",
|
||||
" list_predicted_scores.extend(predicted_scores.tolist())\n",
|
||||
" \n",
|
||||
"# Inserting the scores in df_test\n",
|
||||
"df_test['sp'] = list_predicted_scores\n",
|
||||
"\n",
|
||||
"# Computing the R, MSE and MAE vlaues\n",
|
||||
"correlation, _ = pearsonr(df_test['s'], df_test['sp'])\n",
|
||||
"print(f\"Pearson Correlation Coefficient (R) s: {correlation:.4f}\")\n",
|
||||
"print(f\"Mean Absolute Error (MAE) s: {mean_absolute_error(df_test['s'], df_test['sp']):.4f}\")\n",
|
||||
"print(f\"Root mean Squared Error (RMSE) s: {(mean_squared_error(df_test['s'], df_test['sp'])**(1/2)):.4f}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Evaluating the summary statistics of the testing dataset and the predicted values."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_test[['s', 'sp']].describe()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.14.6"
|
||||
},
|
||||
"vscode": {
|
||||
"interpreter": {
|
||||
"hash": "8c75c0fdd1a718867cdcb84b32adcfdbeaad00b3a4e00a59385211aeed084d4c"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue