In [2]:
#IDEA построить гистограмму распределения слов у Counter
#
# Дальше идет работы с графом с учетом полученного массива сематической близости пар слов
# Соствление нечеткого графа по моногородам (по словам)
# Для построения графа если семантика уже собрана то можно начинать с этого места
# preparation
import pymorphy2
import nltk
import pandas as pd
nltk.download('punkt') #не знаю нужно ли каждый раз это скачивать
nltk.download('stopwords') #не знаю нужно ли каждый раз это скачивать
# Set global params and praparation
morph = pymorphy2.MorphAnalyzer()
g_path = "D:/Projects/Aspirantura/GASU_SP/"
print("g_path >> ",g_path)
g_max_inds_count = 19995 #19995
print("g_max_inds_count >> ",g_max_inds_count)
g_th = 0.4 #start threshold for fuzzy graph
print("g_th >> ",g_th)
print("Done")
In [2]:
# Составление справочника слов и формирование дата сета (матрицы графа) слов и списков показателей и слов
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import pickle
import pymorphy2
import nltk
from nltk.corpus import stopwords
import time
from time import gmtime, strftime
import random
import collections
print("--- Start time %s ---" % strftime("%a, %d %b %Y %H:%M:%S", gmtime()))
start_time = time.time()
print("Start creating Indictors DataSet")
#Загрузка даных
xl_file = pd.ExcelFile(g_path+'Показатели моногородов.xlsx')
ds = xl_file.parse("Лист1")
#clear symbols
# эти символы разбивают слово на два
chars_to_remove = [u'«', u'»', u'!', u'<', u'>', u'?', u',', u'.', u'-', u'(', u')', u'[', u']', u'"']
dd = {ord(c):' ' for c in chars_to_remove}
# эти символы убирают слово из сравнения
stop_sybols = [u'/', u'\\', u'№', u':', u'1', u'2', u'3', u'4' , u'5', u'6', u'7', u'8', u'9', u'0', u'–']
# Загружаем стоп слова
xl_file = pd.ExcelFile(g_path+'Стоп слова.xlsx')
# dfs = {sheet_name: xl_file.parse(sheet_name)
# for sheet_name in xl_file.sheet_names}
ds_stop_words = xl_file.parse("Лист1")
stop_list = [morph.parse(x)[0].normal_form for x in ds_stop_words.STOP_WORDS.str.upper().tolist() ]
# add common stop words
for w in stopwords.words('russian'):
stop_list.append(w)
print("Кол-во стоп слов: ",len(stop_list))
# List of indicators
inds = []
i = 0
l_inds_list = ds.IND_NAME.str.upper().tolist()
if g_max_inds_count < len(l_inds_list)*0.9:
sample_list = random.sample(l_inds_list, g_max_inds_count)
else:
sample_list = l_inds_list[0:g_max_inds_count]
for j in sample_list:
inds.append([i, j, [], {}])
inds[i][2] = [morph.parse(x)[0].normal_form for x in nltk.word_tokenize(j.translate(dd))
if (not any(st in x for st in stop_sybols)) and (morph.parse(x)[0].normal_form not in stop_list)]
i+=1
print("indicators >>", inds[0:10])
output = open(g_path+'monocity_inds_'+str(g_max_inds_count)+'.pkl', 'wb')
pickle.dump(inds, output)
output.close()
print("Indicators saved in ", g_path+'monocity_inds_'+str(g_max_inds_count)+'.pkl')
print("\n--------------------------------------------------------\n")
print("Start creating Words DataSet")
l_words_counter = collections.Counter([w for ind in inds for w in ind[2]]) # получили слова с их количествами
# print("l_words_counter ", l_words_counter)
# теперь нормируем важность слова относительно
l_values = [int(v) for k,v in dict(l_words_counter).items()]
l_cntr_mean = np.mean(l_values)
l_cntr_std = np.std(l_values)
print("l_cntr_mean >> ", l_cntr_mean)
print("l_cntr_std >> ", l_cntr_std)
# l_words_dict = {k: (v-l_cntr_mean)/l_cntr_std for k,v in dict(l_words_counter).items()}
l_words_dict = [ [k, (v-l_cntr_mean)/l_cntr_std] for k,v in dict(l_words_counter).items()]
# words = list(set()) #delete duplicates
print("Words cnt: ", len(l_words_dict))
# l_dt_smpl = {}
# i = 0
# for k,v in l_words_dict.items():
# i +=1
# if i < 10:
# l_dt_smpl[k] = v
# else:
# break
print("Words (normalized) [0:10]>> ", l_words_dict[0:10])
#вывести все слова с частотами в отдельный текстовый файл
l_df = pd.DataFrame(l_words_dict)
l_df.to_csv(g_path+'monocity_words_'+str(g_max_inds_count)+'.csv', index=False, header=True)
print("Words with frequencies saved in ", g_path+'monocity_words_'+str(g_max_inds_count)+'.csv')
print("\n--------------------------------------------------------\n")
# words = list(l_words_dict.keys())
l_words_cnt = len(l_words_dict)
words_ds = [[0 for j in range(0, l_words_cnt)] for i in range(0, l_words_cnt)]
# IDEA может быть повышать важность (силу) связей между словами на основании важности сами слов (частота или еще как) ?
# Semantic dictionary
pkl_file = open(g_path+'words_dict_monocities_sem.pkl', 'rb')
l_words_sem_dist_dict = pickle.load(pkl_file)
pkl_file.close()
l_sem_dict_empty = {k:v for k, v in l_words_sem_dist_dict.items() if v is None } #all not empty
print("Available processed pair count: ", len(l_words_sem_dist_dict)-len(l_sem_dict_empty))
for i in range(0, l_words_cnt):
for j in range(0, l_words_cnt):
if l_words_dict[i][0] == l_words_dict[j][0]: # FIXME actually only when i==j
words_ds[i][j] = 1
words_ds[j][i] = 1
else:
mc=""
m = 0
w1 = l_words_dict[i][0]
w2 = l_words_dict[j][0]
try:
if w1 > w2:
mc=l_words_sem_dist_dict[w1+"__"+w2]
else:
mc=l_words_sem_dist_dict[w2+"__"+w1]
if mc not in [None, "Error", "Unknown"]:
m = abs(float(mc)) # [-1;1] !!!
except:
None
words_ds[i][j] = m
words_ds[j][i] = m
# # добавим сильные связи слов внутри одного показателя
# j = 0
# m = 1
# for ind in inds:
# for j1 in range(0, len(ind[2])):
# if j1>0:
# words_ds[j][j-1] = m
# words_ds[j-1][j] = m
#
# j+=1
output = open(g_path+'monocity_words_ds_'+str(g_max_inds_count)+'.pkl', 'wb')
pickle.dump(words_ds, output)
output.close()
print("Words DS saved in ", g_path+'monocity_words_ds_'+str(g_max_inds_count)+'.pkl')
output = open(g_path+'monocity_words_'+str(g_max_inds_count)+'.pkl', 'wb')
pickle.dump(l_words_dict, output)
output.close()
print("Words dictionary saved in ", g_path+'monocity_words_'+str(g_max_inds_count)+'.pkl')
print("WORDS_DS[5][0:11] example: ", words_ds[5][0:20])
print("Done")
end_time = time.time()
print("--- %s seconds ---" % (end_time - start_time))
In [2]:
# Construct fuzzy graph from WORDS
import igraph
# from igraph import *
import pickle
import time
from time import gmtime, strftime
print("--- Start time %s ---" % strftime("%a, %d %b %Y %H:%M:%S", gmtime()))
start_time = time.time()
#----------------------------------------------------------------------------------------
# def calc_weigth(p_vw1, p_vw2, p_ew) -> float:
# l_vw = max(p_vw1, p_vw2)
# if l_vw > 0:
# l_w = min(1, p_ew + l_vw/10)
# return l_w
# else:
# return p_ew
def calc_weigth(p_vw1, p_vw2, p_ew) -> float:
return p_ew
#----------------------------------------------------------------------------------------
def create_graph(p_words_ds, p_words, p_edge_treshold, p_graph_file_name):
graph_ver_cnt = len(p_words)
g = igraph.Graph()
g.add_vertices(graph_ver_cnt)
# g.vs["name"] = [p_words[i] for i in range(0, graph_ver_cnt)]
g.vs["name"] = [k[0] for k in p_words]
g.vs["norm_weight"] = [k[1] for k in p_words]
# g.vs["cluster_n"] = [0 for i in range(0, graph_ver_cnt)]
# g.vs["cluster_n"] = [0 for k in p_words.items()]
edgs = [ (i,j) for i in range(0, graph_ver_cnt) for j in range(0, graph_ver_cnt)
if i>j and p_words_ds[i][j] >= p_edge_treshold]
# print(edgs)
g.add_edges(edgs)
g.es["weight"] = [ calc_weigth(p_words[i][1], p_words[j][1], p_words_ds[i][j])
for i in range(0, graph_ver_cnt)
for j in range(0, graph_ver_cnt) if i>j and p_words_ds[i][j] > p_edge_treshold
]
# delete isolated vertices
l_exclude_list = []
l_exclude_vs = []
for i in reversed(range(0,graph_ver_cnt)):
if g.vs[i].degree() == 0:
l_exclude_list.append(g.vs[i]["name"])
l_exclude_vs.append(i)
g.delete_vertices(l_exclude_vs)
print("Excluded cnt: ", len(l_exclude_list))
print("Exclude list [0:50]: ", l_exclude_list[0:100])
g.write_graphml(p_graph_file_name)
print("Graph "+p_graph_file_name+" created.")
igraph.summary(g)
return g
#----------------------------------------------------------------------------------------
pkl_file = open(g_path+'monocity_words_ds_'+str(g_max_inds_count)+'.pkl', 'rb')
words_ds = pickle.load(pkl_file)
pkl_file.close()
print("words_ds len: ", len(words_ds))
pkl_file = open(g_path+'monocity_words_'+str(g_max_inds_count)+'.pkl', 'rb')
words = pickle.load(pkl_file)
pkl_file.close()
print("words len: ", len(words))
# for th in [0.5, 0.7, 0.9]:
# for th in [0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]:
for th in [g_th]:
l_graph_main = create_graph(words_ds, words, th,
g_path+"monocity_words_graph_"
+str(g_max_inds_count)+"_"+str(round(th*100))+".graphml"
)
print("Done")
end_time = time.time()
print("--- %s seconds ---" % (end_time - start_time))
In [59]:
# Проверки. Временное
pkl_file = open(g_path+'monocity_words_ds_'+str(g_max_inds_count)+'.pkl', 'rb')
words_ds = pickle.load(pkl_file)
pkl_file.close()
print("words_ds len: ", len(words_ds))
# pkl_file = open(g_path+'monocity_words_'+str(g_max_inds_count)+'.pkl', 'rb')
# words = pickle.load(pkl_file)
# pkl_file.close()
# print("words len: ", len(words))
l_cnt = 0
# for ws in words_ds:
# if max(w for w in ws if w != 1) < 0.001:
# l_cnt +=1
print("l_cnt >> ", l_cnt)
print(l_words_sem_dist_dict["ребёнок__девочка"])
# print(l_words_sem_dist_dict["девочка__ребёнок"])
print(l_words_sem_dist_dict["факт__оборот"])
# print(l_words_sem_dist_dict["оборот__факт"])
# print("None cnt >> ", sum(1 for k,v in l_words_sem_dist_dict.items() if v==None))
# print("Error cnt >> ",sum(1 for k,v in l_words_sem_dist_dict.items() if v=='Error'))
# print("Unknown cnt >> ", sum(1 for k,v in l_words_sem_dist_dict.items() if v=='Unknown'))
i = 0
print("Unknown pairs:")
for k,v in l_words_sem_dist_dict.items():
if v == "Unknown":
print(k)
i += 1
if i > 10:
break
print("Done")
In [19]:
# Hierarchical clustering based on fuzzy connectedness
import igraph
# from igraph import *
import pickle
import time
import random
from time import gmtime, strftime
from typing import List
#---------------------------------------------------------------------------
def del_edges(p_graph: igraph.Graph, p_edge_threshold: float):
for e in p_graph.es:
if e["weight"] < p_edge_threshold:
p_graph.delete_edges(e.index)
# for v in p_graph.vs:
# if v.degree() == 0:
# p_graph.delete_vertices(v.index)
#---------------------------------------------------------------------------
def get_subgraph_weight(p_graph: igraph.Graph) -> float:
# l_degree = p_graph.degree()
l_norm_weight = [1 if v <= 0 else v+1 for v in p_graph.vs["norm_weight"]]
# l_name = p_graph.vs["name"]
l_weight = sum(l_norm_weight[i] for i in range(0, len(p_graph.vs)) )
return l_weight
#---------------------------------------------------------------------------
def get_subgraph_keywords(p_graph: igraph.Graph, p_keyword_cnt: int) -> List[str]:
l_degree = p_graph.degree()
l_norm_weight = [1 if v <= 0 else v+1 for v in p_graph.vs["norm_weight"]]
l_name = p_graph.vs["name"]
l_dict = {l_name[i]: l_degree[i]*l_norm_weight[i] for i in range(0, len(p_graph.vs)) }
return sorted(l_dict, key=l_dict.get, reverse=True)[0:min(p_keyword_cnt, len(p_graph.vs))]
#---------------------------------------------------------------------------
#возвращает разрезанный граф, всегда больше одного подграфа,
# за исключением случая, когда разрезание противоречит органичениям
# старается получить разбиение с заданным количеством значимых (те которые превратятся в узлы) подграфов
def cut_graph(pGraph: igraph.Graph, p_edge_threshold: float,
p_edge_th_step: float,
p_max_edge_threshold: float,
p_avg_bouquet: int,
p_min_subgraph_coeff: float = 10 #коэффициент при котором субграф добавляется в иерархию
) -> [[igraph.Graph], float]:
l_edge_threshold = p_edge_threshold
l_prev_sgs_cnt = 1
l_prev_sgs = [pGraph]
l_sgs = [pGraph]
#пока возможно разбиение
while (l_edge_threshold<1) and (l_edge_threshold < p_max_edge_threshold):
del_edges(pGraph, l_edge_threshold)
l_comps = pGraph.components(mode='STRONG') #Returns:a VertexClustering object
l_sgs = l_comps.subgraphs()
l_sgs_cnt = sum(1 if (get_subgraph_weight(sg) >= p_min_subgraph_coeff) else 0 for sg in l_sgs)
#подходит ли нам такое рзбиение?
#если разбиаение подошло то выходим из цикла
if (l_prev_sgs_cnt == 1) and (l_sgs_cnt >= p_avg_bouquet):
break
else:
# единственная ситуация продолжения разбиения: не достигли среднего
if (l_prev_sgs_cnt == 1) and (l_sgs_cnt < p_avg_bouquet):
l_prev_sgs_cnt = l_sgs_cnt
l_prev_sgs = l_sgs
else:
# если отклонение от среднего количества на предыдущем шаге было меньше, то возвращаем его
if abs(l_prev_sgs_cnt - p_avg_bouquet) < abs(l_sgs_cnt - p_avg_bouquet):
l_sgs = l_prev_sgs
break
# достигои идеального количества подграфов
else:
break
#шаг для следующего разбиения
l_edge_threshold += p_edge_th_step
# if abs(l_edge_threshold - p_edge_threshold) > 10E-4:
# print("Different th ", l_edge_threshold, " ", p_edge_threshold)
return [l_sgs, l_edge_threshold]
#---------------------------------------------------------------------------
def add_layer(p_hier_graph: igraph.Graph, p_graph: igraph.Graph, p_parent_vtx: str,
p_layer_n: int,
p_edge_threshold: float, #уровень с которого нужно начинать разбивать граф (для первого случая это текущий уровень)
p_edge_th_step: float,
p_max_edge_threshold: float,
p_max_layer_cnt: int,
p_min_subgraph_coeff: float = 10, #коэффициент при котором субграф добавляется в иерархию
p_keywords_cnt: int = 10, #количество ключевых слов для узла
p_keyword_coeff: float = 100, #коэффициент значимости первого слова от каждого подграфа
p_avg_bouquet: int = 4
) -> {str: int}:
#нарежем граф так, чтобы было нужно число подграфов (получим один подграф, только если разрезать не возможно)
l_edge_threshold = p_edge_threshold
if p_layer_n > 1: #первый шаг уже приходит нарезанным, поэтому для него условие ELSE
[sgs, l_edge_threshold] = cut_graph(p_graph, l_edge_threshold, p_edge_th_step, p_max_edge_threshold, p_avg_bouquet, p_min_subgraph_coeff)
else: #первый шаг особенный
l_comps = p_graph.components(mode='STRONG') #Returns:a VertexClustering object
sgs = l_comps.subgraphs()
if len(sgs) == 1: #если в самом начале нам дали не разбитый граф, то нужно его тоже разбить
[sgs, l_edge_threshold] = cut_graph(p_graph, l_edge_threshold+p_edge_th_step, p_edge_th_step, p_max_edge_threshold, p_avg_bouquet, p_min_subgraph_coeff)
#устанавливаем начальные переменные
l_keywords = {}
l_prnt_index = len(p_hier_graph.vs)-1
l_node_cnt = 1 # если считать с нуля то будет умножение на ноль и пропадут многие ключевые сслова
#проходимся по всем подграфам
for sg in sgs:
l_sg_keywords = {}
# l_sg_vrtx_indx = 0
# если вес данного подграфа достин собственного узла в иерархии то
# также у нас теперь не может граф распадаться только на одну вершину, мы этого не допускаем процедурой разрезания
# if (get_subgraph_weight(sg) >= p_min_subgraph_coeff) or (len(sgs) == 1):
if (get_subgraph_weight(sg) >= p_min_subgraph_coeff) and (len(sgs) != 1):
# Add vertex
# TODO от такого именования нужно будет уйти на более абстрактное, когда будут ключевые слова сделаны
if len(sg.vs) > p_keywords_cnt:
l_vrtx_name = "Layer "+str(p_layer_n)+" "+' '.join(list(random.sample(sg.vs["name"], 3)))
else:
l_vrtx_name = "Layer "+str(p_layer_n)+" "+' '.join(list(sg.vs["name"]))
p_hier_graph.add_vertex(l_vrtx_name)
l_sg_vrtx_indx = len(p_hier_graph.vs)-1
# print(l_sg_vrtx_indx)
l_node_cnt += 1
p_hier_graph.vs["layer"] = ["Layer "+str(l_edge_threshold) if x is None else x for x in p_hier_graph.vs["layer"]]
p_hier_graph.vs["layer_n"] = [l_edge_threshold if x is None else x for x in p_hier_graph.vs["layer_n"]]
p_hier_graph.vs["graph"] = [sg if x is None else x for x in p_hier_graph.vs["graph"]]
p_hier_graph.vs["parent_node"] = ["n"+str(l_prnt_index) if x is None else x for x in p_hier_graph.vs["parent_node"]]
p_hier_graph.add_edge(p_parent_vtx, l_vrtx_name)
# Recursion
l_next_edge_threshold = l_edge_threshold+p_edge_th_step
#Условие входа в рекурсию:
#создавали узел
#максимальное число шагов не достигнуто
if (len(sg.vs)>1) and (p_layer_n < p_max_layer_cnt) and (l_next_edge_threshold<1) and (l_next_edge_threshold < p_max_edge_threshold):
# del_edges(sg, p_edge_threshold)
l_sg_keywords = add_layer(p_hier_graph, sg, l_vrtx_name, p_layer_n+1, l_next_edge_threshold, p_edge_th_step, p_max_edge_threshold,
p_max_layer_cnt, p_min_subgraph_coeff, p_keywords_cnt, p_keyword_coeff, p_avg_bouquet)
i = 0
for k,v in l_sg_keywords.items(): #пополним список ключевых слов родительской вершины
if i == 0:
l_keywords[k] = v*p_keyword_coeff
else:
l_keywords[k] = v
i += 1
else: # в рекурсию не вошли, значит просто пополняем список ключевых слов родителя
i = 0
for w in get_subgraph_keywords(sg, p_keywords_cnt):
if i == 0:
l_keywords[w] = 1*p_keyword_coeff
else:
l_keywords[w] = 1
l_sg_keywords[w] = 1
i += 1
# Для добавленного узла нужно вставить его ключевые слова и количество детей
l_words = ' '.join(l_sg_keywords.keys())
# print(l_words)
# print(p_hier_graph.vs["keywords"][0:5])
p_hier_graph.vs["keywords"] = [l_words if i == l_sg_vrtx_indx else p_hier_graph.vs["keywords"][i]
for i in range(0, len(p_hier_graph.vs))
]
# print(p_hier_graph.vs["keywords"][0:5])
p_hier_graph.vs["child_node_cnt"] = [len(sg.vs()) if i == l_sg_vrtx_indx else p_hier_graph.vs["child_node_cnt"][i]
for i in range(0, len(p_hier_graph.vs))
]
# если вес данного подграфа НЕ достин собственного узла в иерархии то просто пополняем ключевые слова родителя
else:
# just add keywords
i = 0
for w in get_subgraph_keywords(sg, p_keywords_cnt):
if i == 0:
l_keywords[w] = 1*p_keyword_coeff
else:
l_keywords[w] = 1
i += 1
# if p_layer_n == 1:
# print(l_keywords)
l_list = sorted(l_keywords, key=l_keywords.get, reverse=True)[0:p_keywords_cnt] # у нас уже столько сколько нужно слов
return {k: l_node_cnt for k in l_list}
#---------------------------------------------------------------------------
def getEdgeStat(pGraph: igraph.Graph) -> [float, float, float]:
if len(pGraph.es["weight"]) == 0:
return [1,1,1]
l_max = max(w for w in pGraph.es["weight"])
l_min = min(w for w in pGraph.es["weight"])
l_avg = sum(w for w in pGraph.es["weight"])/len(pGraph.es["weight"])
return [l_max, l_min, l_avg]
#---------------------------------------------------------------------------
def getVertexStat(pGraph: igraph.Graph) -> float:
l_sum = sum(vw for vw in p_graph.vs["norm_weight"])
return [l_min, l_avg, l_max]
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
# main part
print("--- Start time %s ---" % strftime("%a, %d %b %Y %H:%M:%S", gmtime()))
start_time = time.time()
#parameters
l_th = g_th #0.4
l_max_inds_count = g_max_inds_count #19995 # для определения имени файлов для чтения и запии
l_th_start = l_th # старовый уровень уничтоженных ребер
l_th_step = 0.01 # шаг рекурсии по уничтожению ребер
l_th_max = 0.99 # максимальный уровень до которого уничтожаем ребра
l_max_depth = 1000 #максимальная глубина рекурсии
l_avg_bouquet = 3 # целевое количество подузлов в дереве
l_min_subgraph_coeff = 9.0 #коэффициент при котором субграф добавляется в иерархию
l_keywords_cnt = 10 #количество ключевых слов определяющих узел
l_keyword_coeff = 100 # множитель для первого слова в ключевых словах от каждого узла (чтобы один узел не затмил своими словами другие)
#load graph
l_graph_main = igraph.Graph().Load(g_path+"monocity_words_graph_"
+str(l_max_inds_count)+"_"+str(round(l_th*100))+".graphml"
)
print("Main graph summary: ", l_graph_main.summary())
l_hier_graph = igraph.Graph() # результирующий иерархический граф
l_hier_graph.add_vertices(1)
l_hier_graph.vs["name"] = ["_Моногорода_"]
l_hier_graph.vs["keywords"] = ["_Моногорода_"]
l_hier_graph.vs["layer"] = ["Layer "+str(0)]
l_hier_graph.vs["layer_n"] = [0]
l_hier_graph.vs["child_node_cnt"] = [len(l_graph_main.vs)]
l_hier_graph.vs["parent_node"] = ["n"]
l_hier_graph.vs["graph"] = [l_graph_main]
# l_hier_graph.vs["child_cnt"] = [-1]
# l_hier_graph.vs["child"] = [[]]
l_layer = 1
l_parent_vrtx_name = "_Моногорода_"
# l_comps = l_graph_main.components(mode='STRONG') #Returns:a VertexClustering object
# l_layer += 1
l_mono_dict = add_layer(l_hier_graph, l_graph_main, l_parent_vrtx_name, l_layer,
l_th_start, l_th_step, l_th_max,
l_max_depth,
l_min_subgraph_coeff, l_keywords_cnt, l_keyword_coeff,
l_avg_bouquet
)
# print(add_layer(l_hier_graph, l_graph_main, l_parent_vrtx_name, l_layer, 0.75, 0.95, 0.05, 7))
l_words = ' '.join(l_mono_dict.keys())
l_hier_graph.vs["keywords"] = [l_words if i == 0 else l_hier_graph.vs["keywords"][i]
for i in range(0, len(l_hier_graph.vs))
]
l_hier_graph.vs["child_cnt"] = l_hier_graph.degree()
# l_hier_graph.vs["child"] = [l_words if i == 0 else l_hier_graph.vs["child"][i]
# for i in range(0, len(l_hier_graph.vs))
# ]
print("Hier graph summary: ", l_hier_graph.summary())
print("Graphs' samples: ", l_hier_graph.vs["parent_node"][0:15])
print("Graphs' in hierarchy: ", len(l_hier_graph.vs["graph"]))
print("Graphs' samples: ", l_hier_graph.vs["graph"][0:5])
print("One graph words sample: ", l_hier_graph.vs["graph"][0].vs["name"][0:10])
#Вычислим дополнительные полезные характеристики
# - суммарный вес слов
# - мин макс и среднее значение веса ребер
l_hier_graph.vs["subgraph_weigth"] = [get_subgraph_weight(sg) for sg in l_hier_graph.vs["graph"]]
l_sg_edge_stats = [getEdgeStat(sg) for sg in l_hier_graph.vs["graph"]]
l_hier_graph.vs["subgraph_edge_mins"] = [i[0] for i in l_sg_edge_stats]
l_hier_graph.vs["subgraph_edge_avgs"] = [i[1] for i in l_sg_edge_stats]
l_hier_graph.vs["subgraph_edge_maxs"] = [i[2] for i in l_sg_edge_stats]
l_hier_graph.write_graphml(g_path+"monocity_words_hier_graph_"
+str(l_max_inds_count)+"_"+str(round(l_th*100))+".graphml"
)
print("Graph file: "+g_path+"monocity_words_hier_graph_"
+str(l_max_inds_count)+"_"+str(round(l_th*100))+".graphml"
)
print("Done")
end_time = time.time()
print("--- %s seconds ---" % (end_time - start_time))
#---------------------------------------------------------------------------
In [20]:
# Indicators fuzzy clustering
# выполняется всегда сразу после предыдущего пункта, т.к. тут не загружается граф иерархический
import igraph
# from igraph import *
import pickle
import time
import random
from time import gmtime, strftime
from typing import List
#---------------------------------------------------------------------------
# main part
print("--- Start time %s ---" % strftime("%a, %d %b %Y %H:%M:%S", gmtime()))
start_time = time.time()
#parameters
l_th = g_th #0.4
l_max_inds_count = g_max_inds_count #19995 # для определения имени файлов для чтения и запии
# l_th_start = l_th # старовый уровень уничтоженных ребер
# l_th_step = 0.01 # шаг рекурсии по уничтожению ребер
# l_th_max = 0.9 # максимальный уровень до которого уничтожаем ребра
# l_max_depth = 20 #максимальная глубина рекурсии
#
# l_min_subgraph_coeff = 3.0 #коэффициент при котором субграф добавляется в иерархию
# l_keywords_cnt = 10 #количество ключевых слов определяющих узел
# l_keyword_coeff = 100 # множитель для первого слова в ключевых словах от каждого узла (чтобы один узел не затмил своими словами другие)
#load graph
# l_hier_graph = igraph.Graph().Load("D:/Projects/Aspirantura/GASU_SP/monocity_words_hier_graph_"
# +str(l_max_inds_count)+"_"+str(round(l_th*100))+".graphml"
# )
#load indicators
pkl_file = open(g_path+'monocity_inds_'+str(l_max_inds_count)+'.pkl', 'rb')
inds = pickle.load(pkl_file)
pkl_file.close()
print("Inds len: ", len(inds))
for v in l_hier_graph.vs:
for i in inds:
if len(i[2])>0:
l_cnt = 0
l_index = v.index
l_graphs = l_hier_graph.vs["graph"]
l_graph = l_graphs[l_index]
for w in l_graph.vs:
if w["name"] in i[2]:
l_cnt += 1
# print(i[0])
l_pcnt = l_cnt/len(i[2])
if l_pcnt > 0.1:
i[3][l_index] = round(l_pcnt,3)
print("Inds sample [0:10]: ", inds[0:9])
#write indicators
output = open(g_path+'monocity_inds_hier_'+str(l_max_inds_count)+'.pkl', 'wb')
pickle.dump(inds, output)
output.close()
#write indicators to csv
l_df = pd.DataFrame(inds)
l_df.to_csv(g_path+'monocity_inds_hier_'+str(g_max_inds_count)+'.csv', index=False, header=True)
print("Indicators clustering results saved in ", g_path+'monocity_inds_hier_'+str(g_max_inds_count)+'.csv')
print("Done")
end_time = time.time()
print("--- %s seconds ---" % (end_time - start_time))
#---------------------------------------------------------------------------
In [7]:
# test fuzzy hierarchical clustering results
import igraph
# from igraph import *
import pickle
import time
import random
from time import gmtime, strftime
from typing import List
#---------------------------------------------------------------------------
#parameters
l_th = g_th
l_max_inds_count = g_max_inds_count # для определения имени файлов для чтения и запии
#---------------------------------------------------------------------------
def getIndicatorsByNode(pNodeIndex: int, pInds: list) -> []:
l_list=[]
for i in pInds:
l_pt = i[3].get(pNodeIndex, None)
if l_pt != None:
l_list.append([i, l_pt])
l_list.sort(key=lambda arg: arg[1], reverse=True)
return l_list
#---------------------------------------------------------------------------
# main part
print("--- Start time %s ---" % strftime("%a, %d %b %Y %H:%M:%S", gmtime()))
start_time = time.time()
# load graph
l_hier_graph = igraph.Graph().Load(g_path+'monocity_words_hier_graph_'+str(g_max_inds_count)+"_"+str(round(g_th*100))+".graphml")
#load indicators
pkl_file = open(g_path + 'monocity_inds_hier_'+str(l_max_inds_count)+'.pkl', 'rb')
inds = pickle.load(pkl_file)
pkl_file.close()
# print("Inds len: ", len(inds))
# for n in [65, 83, 85, 91, 93, 41]:
for n in [596, 600, 601, 594]:
print("Node ID: ", n, " keywords: ", l_hier_graph.vs["keywords"][n])
l_inds = getIndicatorsByNode(n, inds)
print("Inds cnt: ", len(l_inds))
print("Inds sample [0:10]:")
for i in l_inds[0:10]:
print(i[1]," - ",i[0][0]," - ",i[0][1])
print("----------------------------------")
print("Done")
end_time = time.time()
print("--- %s seconds ---" % (end_time - start_time))
#---------------------------------------------------------------------------
In [21]:
# Для более содержательного анализа было бы хорошо модифицировать наш граф, добавив туда еще два свойства
# - количесво показателей ассоциированных с вершний
# - общий вес показателей ассоциированных с вершиной
import igraph
# from igraph import *
import pickle
import time
import random
from time import gmtime, strftime
from typing import List
#---------------------------------------------------------------------------
#parameters
l_th = g_th
l_max_inds_count = g_max_inds_count # для определения имени файлов для чтения и запии
#---------------------------------------------------------------------------
def getIndicatorsByNode(pNodeIndex: int, pInds: list) -> []:
l_list=[]
for i in pInds:
l_pt = i[3].get(pNodeIndex, None)
if l_pt != None:
l_list.append([i, l_pt])
l_list.sort(key=lambda arg: arg[1], reverse=True)
return l_list
#---------------------------------------------------------------------------
# main part
print("--- Start time %s ---" % strftime("%a, %d %b %Y %H:%M:%S", gmtime()))
start_time = time.time()
# load graph
l_hier_graph = igraph.Graph().Load(g_path+'monocity_words_hier_graph_'+str(g_max_inds_count)+"_"+str(round(g_th*100))+".graphml")
#load indicators
pkl_file = open(g_path + 'monocity_inds_hier_'+str(l_max_inds_count)+'.pkl', 'rb')
inds = pickle.load(pkl_file)
pkl_file.close()
# print("Inds len: ", len(inds))
l_inds_cnt = []
l_ind_weigths = []
for v in l_hier_graph.vs():
l_inds = getIndicatorsByNode(v.index, inds)
l_inds_cnt.append(len(l_inds))
l_ind_weigths.append(sum(i[1] for i in l_inds))
l_hier_graph.vs["inds_cnt"] = l_inds_cnt
l_hier_graph.vs["inds_weigth"] = l_ind_weigths
l_hier_graph.write_graphml(g_path+"monocity_words_hier_graph_"
+str(l_max_inds_count)+"_"+str(round(l_th*100))+".graphml"
)
print("Graph file: "+g_path+"monocity_words_hier_graph_"
+str(l_max_inds_count)+"_"+str(round(l_th*100))+".graphml"
)
print("Done")
end_time = time.time()
print("--- %s seconds ---" % (end_time - start_time))
#---------------------------------------------------------------------------
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]: