tmplot 0.1.2__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: tmplot
3
- Version: 0.1.2
3
+ Version: 0.2.0
4
4
  Summary: Visualization of Topic Modeling Results
5
5
  Author-email: Maksim Terpilovskii <maximtrp@gmail.com>
6
6
  License: MIT License
@@ -96,6 +96,12 @@ Requires-Dist: bitermplus; extra == "models"
96
96
  - LocallyLinearEmbedding
97
97
  - Isomap
98
98
 
99
+ ## Donate
100
+
101
+ If you find this package useful, please consider donating any amount of money. This will help me spend more time on supporting open-source software.
102
+
103
+ <a href="https://www.buymeacoffee.com/maximtrp" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>
104
+
99
105
  ## Installation
100
106
 
101
107
  The package can be installed from PyPi:
@@ -38,6 +38,12 @@
38
38
  - LocallyLinearEmbedding
39
39
  - Isomap
40
40
 
41
+ ## Donate
42
+
43
+ If you find this package useful, please consider donating any amount of money. This will help me spend more time on supporting open-source software.
44
+
45
+ <a href="https://www.buymeacoffee.com/maximtrp" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>
46
+
41
47
  ## Installation
42
48
 
43
49
  The package can be installed from PyPi:
@@ -5,4 +5,4 @@ from ._stability import * # noqa: F401, F403
5
5
  from ._vis import * # noqa: F401, F403
6
6
  from ._metrics import * # noqa: F401, F403
7
7
 
8
- __version__ = '0.1.2'
8
+ __version__ = '0.2.0'
@@ -1,13 +1,17 @@
1
- __all__ = [
2
- 'get_topics_dist', 'get_topics_scatter', 'get_top_topic_words']
3
- from typing import Union, List
1
+ __all__ = ["get_topics_dist", "get_topics_scatter", "get_top_topic_words"]
2
+ from typing import Optional, Union, List
4
3
  from itertools import combinations
5
- from pandas import DataFrame
4
+ from pandas import DataFrame, Index
6
5
  import numpy as np
7
6
  from scipy.special import kl_div
8
7
  from scipy.spatial import distance
9
8
  from sklearn.manifold import (
10
- TSNE, Isomap, LocallyLinearEmbedding, MDS, SpectralEmbedding)
9
+ TSNE,
10
+ Isomap,
11
+ LocallyLinearEmbedding,
12
+ MDS,
13
+ SpectralEmbedding,
14
+ )
11
15
  from ._helpers import calc_topics_marg_probs
12
16
 
13
17
 
@@ -28,15 +32,14 @@ def _dist_jsd(a1: np.ndarray, a2: np.ndarray):
28
32
 
29
33
  def _dist_jef(a1: np.ndarray, a2: np.ndarray):
30
34
  vals = (a1 - a2) * (np.log(a1) - np.log(a2))
31
- vals[(vals <= 0) | ~np.isfinite(vals)] = 0.
35
+ vals[(vals <= 0) | ~np.isfinite(vals)] = 0.0
32
36
  return vals.sum()
33
37
 
34
38
 
35
39
  def _dist_hel(a1: np.ndarray, a2: np.ndarray):
36
40
  a1[(a1 <= 0) | ~np.isfinite(a1)] = 1e-64
37
41
  a2[(a2 <= 0) | ~np.isfinite(a2)] = 1e-64
38
- hel_val = distance.euclidean(
39
- np.sqrt(a1), np.sqrt(a2)) / np.sqrt(2)
42
+ hel_val = distance.euclidean(np.sqrt(a1), np.sqrt(a2)) / np.sqrt(2)
40
43
  return hel_val
41
44
 
42
45
 
@@ -52,9 +55,9 @@ def _dist_tv(a1: np.ndarray, a2: np.ndarray):
52
55
  return dist
53
56
 
54
57
 
55
- def _dist_jac(a1: np.ndarray, a2: np.ndarray, top_words=100):
56
- a = np.argsort(a1)[:-top_words-1:-1]
57
- b = np.argsort(a2)[:-top_words-1:-1]
58
+ def _dist_jac(a1: np.ndarray, a2: np.ndarray, top_words=100):
59
+ a = np.argsort(a1)[: -top_words - 1 : -1]
60
+ b = np.argsort(a2)[: -top_words - 1 : -1]
58
61
  j_num = np.intersect1d(a, b, assume_unique=False).size
59
62
  j_den = np.union1d(a, b).size
60
63
  jac_val = 1 - j_num / j_den
@@ -62,9 +65,8 @@ def _dist_jac(a1: np.ndarray, a2: np.ndarray, top_words=100):
62
65
 
63
66
 
64
67
  def get_topics_dist(
65
- phi: Union[np.ndarray, DataFrame],
66
- method: str = "sklb",
67
- **kwargs) -> np.ndarray:
68
+ phi: Union[np.ndarray, DataFrame], method: str = "sklb", **kwargs
69
+ ) -> np.ndarray:
68
70
  """Finding closest topics in models.
69
71
 
70
72
  Parameters
@@ -110,16 +112,18 @@ def get_topics_dist(
110
112
  for i, j in topics_pairs:
111
113
  _dist_func = dist_funcs.get(method, "sklb")
112
114
  topics_dists[((i, j), (j, i))] = _dist_func(
113
- phi_copy[:, i], phi_copy[:, j], **kwargs)
115
+ phi_copy[:, i], phi_copy[:, j], **kwargs
116
+ )
114
117
 
115
118
  return topics_dists
116
119
 
117
120
 
118
121
  def get_topics_scatter(
119
- topic_dists: np.ndarray,
120
- theta: np.ndarray,
121
- method: str = 'tsne',
122
- method_kws: dict = None) -> DataFrame:
122
+ topic_dists: np.ndarray,
123
+ theta: np.ndarray,
124
+ method: str = "tsne",
125
+ method_kws: Optional[dict] = None,
126
+ ) -> DataFrame:
123
127
  """Calculate topics coordinates for a scatter plot.
124
128
 
125
129
  Parameters
@@ -146,52 +150,52 @@ def get_topics_scatter(
146
150
  Topics scatter coordinates.
147
151
  """
148
152
  if not method_kws:
149
- method_kws = {'n_components': 2}
153
+ method_kws = {"n_components": 2}
150
154
 
151
- if method == 'tsne':
152
- method_kws.setdefault('init', 'pca')
153
- method_kws.setdefault('learning_rate', 'auto')
154
- method_kws.setdefault(
155
- 'perplexity', min(50, max(topic_dists.shape[0] // 2, 1)))
155
+ if method == "tsne":
156
+ method_kws.setdefault("init", "pca")
157
+ method_kws.setdefault("learning_rate", "auto")
158
+ method_kws.setdefault("perplexity", min(50, max(topic_dists.shape[0] // 2, 1)))
156
159
  transformer = TSNE(**method_kws)
157
160
 
158
- elif method == 'sem':
159
- method_kws.setdefault('affinity', 'precomputed')
161
+ elif method == "sem":
162
+ method_kws.setdefault("affinity", "precomputed")
160
163
  transformer = SpectralEmbedding(**method_kws)
161
164
 
162
- elif method == 'mds':
163
- method_kws.setdefault('dissimilarity', 'precomputed')
164
- method_kws.setdefault('normalized_stress', 'auto')
165
+ elif method == "mds":
166
+ method_kws.setdefault("dissimilarity", "precomputed")
167
+ method_kws.setdefault("normalized_stress", "auto")
165
168
  transformer = MDS(**method_kws)
166
169
 
167
- elif method == 'lle':
168
- method_kws['method'] = 'standard'
170
+ elif method == "lle":
171
+ method_kws["method"] = "standard"
169
172
  transformer = LocallyLinearEmbedding(**method_kws)
170
173
 
171
- elif method == 'ltsa':
172
- method_kws['method'] = 'ltsa'
174
+ elif method == "ltsa":
175
+ method_kws["method"] = "ltsa"
173
176
  transformer = LocallyLinearEmbedding(**method_kws)
174
177
 
175
- elif method == 'isomap':
178
+ elif method == "isomap":
176
179
  transformer = Isomap(**method_kws)
177
180
 
178
181
  coords = transformer.fit_transform(topic_dists)
179
182
 
180
- topics_xy = DataFrame(coords, columns=['x', 'y'])
181
- topics_xy['topic'] = topics_xy.index.astype(int)
182
- topics_xy['size'] = calc_topics_marg_probs(theta)
183
- size_sum = topics_xy['size'].sum()
183
+ topics_xy = DataFrame(coords, columns=Index(["x", "y"]))
184
+ topics_xy["topic"] = topics_xy.index.astype(int)
185
+ topics_xy["size"] = calc_topics_marg_probs(theta)
186
+ size_sum = topics_xy["size"].sum()
184
187
  if size_sum > 0:
185
- topics_xy['size'] *= (100 / topics_xy['size'].sum())
188
+ topics_xy["size"] *= 100 / topics_xy["size"].sum()
186
189
  else:
187
- topics_xy['size'] = np.nan
190
+ topics_xy["size"] = np.nan
188
191
  return topics_xy
189
192
 
190
193
 
191
194
  def get_top_topic_words(
192
- phi: DataFrame,
193
- words_num: int = 20,
194
- topics_idx: Union[List[int], np.ndarray] = None) -> DataFrame:
195
+ phi: DataFrame,
196
+ words_num: int = 20,
197
+ topics_idx: Optional[Union[List[int], np.ndarray]] = None,
198
+ ) -> DataFrame:
195
199
  """Select top topic words from a fitted model.
196
200
 
197
201
  Parameters
@@ -209,9 +213,6 @@ def get_top_topic_words(
209
213
  DataFrame
210
214
  Words with highest probabilities in all (or selected) topics.
211
215
  """
212
- return phi.loc[:, topics_idx or phi.columns]\
213
- .apply(
214
- lambda x: x
215
- .sort_values(ascending=False)
216
- .head(words_num).index, axis=0
216
+ return phi.loc[:, topics_idx or phi.columns].apply(
217
+ lambda x: x.sort_values(ascending=False).head(words_num).index, axis=0
217
218
  )
@@ -1,9 +1,14 @@
1
1
  __all__ = [
2
- 'get_phi', 'get_theta',
3
- 'get_relevant_terms', 'get_salient_terms',
4
- 'get_docs', 'get_top_docs',
5
- 'calc_terms_marg_probs', 'calc_topics_marg_probs',
6
- 'calc_terms_probs_ratio']
2
+ "get_phi",
3
+ "get_theta",
4
+ "get_relevant_terms",
5
+ "get_salient_terms",
6
+ "get_docs",
7
+ "get_top_docs",
8
+ "calc_terms_marg_probs",
9
+ "calc_topics_marg_probs",
10
+ "calc_terms_probs_ratio",
11
+ ]
7
12
  from warnings import warn
8
13
  from importlib.util import find_spec
9
14
  from typing import Union, Optional, Sequence, List
@@ -13,7 +18,7 @@ from numpy import ndarray, zeros, argsort, array, arange, vstack
13
18
  from numpy import log as nplog
14
19
  from pandas import concat, Series, DataFrame
15
20
 
16
- tomotopy_installed = find_spec('tomotopy')
21
+ tomotopy_installed = find_spec("tomotopy")
17
22
  if tomotopy_installed:
18
23
  from tomotopy import (
19
24
  LDAModel as tomotopyLDA,
@@ -23,14 +28,15 @@ if tomotopy_installed:
23
28
  HDPModel as tomotopyHDP,
24
29
  PTModel as tomotopyPT,
25
30
  SLDAModel as tomotopySLDA,
26
- GDMRModel as tomotopyGDMR)
31
+ GDMRModel as tomotopyGDMR,
32
+ )
27
33
 
28
- gensim_installed = find_spec('gensim')
34
+ gensim_installed = find_spec("gensim")
29
35
  if gensim_installed:
30
36
  from gensim.models.ldamodel import LdaModel as gensimLDA
31
37
  from gensim.models.ldamulticore import LdaMulticore as gensimLDAMC
32
38
 
33
- bitermplus_installed = find_spec('bitermplus')
39
+ bitermplus_installed = find_spec("bitermplus")
34
40
  if bitermplus_installed:
35
41
  from bitermplus._btm import BTM
36
42
 
@@ -38,12 +44,11 @@ if bitermplus_installed:
38
44
  def __warn_package_installation(package_name: str):
39
45
  warn(
40
46
  f'Please install "{package_name}" package to analyze its models.\n'
41
- f'Run `pip install {package_name}` in the console.')
47
+ f"Run `pip install {package_name}` in the console."
48
+ )
42
49
 
43
50
 
44
- def get_phi(
45
- model: object,
46
- vocabulary: Optional[Sequence] = None) -> DataFrame:
51
+ def get_phi(model: object, vocabulary: Optional[Sequence] = None) -> DataFrame:
47
52
  """Get words vs topics matrix (phi).
48
53
 
49
54
  Returns ``phi`` matrix of shape W x T, where W is the number of words,
@@ -65,7 +70,6 @@ def get_phi(
65
70
  phi = None
66
71
 
67
72
  if _is_tomotopy(model):
68
-
69
73
  # Topics vs words distributions
70
74
  twd = list(map(model.get_topic_word_dist, range(model.k)))
71
75
 
@@ -76,7 +80,6 @@ def get_phi(
76
80
  phi.index = list(model.used_vocabs)
77
81
 
78
82
  elif _is_gensim(model):
79
-
80
83
  phi = DataFrame(model.get_topics().T)
81
84
  if vocabulary:
82
85
  phi.index = vocabulary
@@ -85,8 +88,8 @@ def get_phi(
85
88
  phi = model.df_words_topics_
86
89
 
87
90
  if isinstance(phi, DataFrame):
88
- phi.index.name = 'words'
89
- phi.columns.name = 'topics'
91
+ phi.index.name = "words"
92
+ phi.columns.name = "topics"
90
93
 
91
94
  return phi
92
95
 
@@ -94,8 +97,15 @@ def get_phi(
94
97
  def _is_tomotopy(model: object) -> bool:
95
98
  if tomotopy_installed:
96
99
  tomotopy_models = [
97
- tomotopyLDA, tomotopyLLDA, tomotopyCT, tomotopyDMR, tomotopyHDP,
98
- tomotopyPT, tomotopySLDA, tomotopyGDMR]
100
+ tomotopyLDA,
101
+ tomotopyLLDA,
102
+ tomotopyCT,
103
+ tomotopyDMR,
104
+ tomotopyHDP,
105
+ tomotopyPT,
106
+ tomotopySLDA,
107
+ tomotopyGDMR,
108
+ ]
99
109
  return any(map(partial(isinstance, model), tomotopy_models))
100
110
 
101
111
  __warn_package_installation("tomotopy")
@@ -119,9 +129,7 @@ def _is_btmplus(model: object) -> bool:
119
129
  return False
120
130
 
121
131
 
122
- def get_theta(
123
- model: object,
124
- corpus: Optional[List] = None) -> DataFrame:
132
+ def get_theta(model: object, corpus: Optional[List] = None) -> Optional[DataFrame]:
125
133
  """Get topics vs documents (theta) matrix.
126
134
 
127
135
  Returns theta matrix of shape T x D, where T is the number of topics,
@@ -132,7 +140,7 @@ def get_theta(
132
140
  model : object
133
141
  Topic model instance.
134
142
  corpus : Optional[List], optional
135
- Corpus.
143
+ Corpus (must be specified for a `gensim` model).
136
144
 
137
145
  Returns
138
146
  -------
@@ -147,8 +155,7 @@ def get_theta(
147
155
 
148
156
  elif _is_gensim(model):
149
157
  if corpus is None:
150
- raise ValueError(
151
- '`corpus` must be supplied for a gensim model')
158
+ raise ValueError("`corpus` must be supplied for a gensim model")
152
159
  tdd = list(map(model.get_document_topics, corpus))
153
160
  theta = DataFrame(zeros((len(tdd), model.num_topics)))
154
161
  for doc_id, doc_topic in enumerate(tdd):
@@ -160,14 +167,13 @@ def get_theta(
160
167
  theta = DataFrame(model.matrix_topics_docs_)
161
168
 
162
169
  if isinstance(theta, DataFrame):
163
- theta.index.name = 'topics'
164
- theta.columns.name = 'docs'
170
+ theta.index.name = "topics"
171
+ theta.columns.name = "docs"
165
172
 
166
173
  return theta
167
174
 
168
175
 
169
- def get_docs(
170
- model: object) -> List[str]:
176
+ def get_docs(model: object) -> Optional[List[str]]:
171
177
  """Retrieve documents from topic model object.
172
178
 
173
179
  Parameters
@@ -183,19 +189,19 @@ def get_docs(
183
189
  if _is_tomotopy(model):
184
190
  docs_raw = map(lambda x: x.words, model.docs)
185
191
  return list(
186
- map(
187
- lambda doc: " ".join(map(lambda x: model.vocabs[x], doc)),
188
- docs_raw))
192
+ map(lambda doc: " ".join(map(lambda x: model.vocabs[x], doc)), docs_raw)
193
+ )
189
194
  return None
190
195
 
191
196
 
192
197
  def get_top_docs(
193
- docs: Sequence[str],
194
- model: object = None,
195
- theta: ndarray = None,
196
- corpus: Optional[List] = None,
197
- docs_num: int = 5,
198
- topics: Sequence[int] = None) -> DataFrame:
198
+ docs: Sequence[str],
199
+ model: object = None,
200
+ theta: Optional[ndarray] = None,
201
+ corpus: Optional[List] = None,
202
+ docs_num: int = 5,
203
+ topics: Optional[Sequence[int]] = None,
204
+ ) -> DataFrame:
199
205
  """Get top documents for all (or a selected) topic.
200
206
 
201
207
  Parameters
@@ -231,20 +237,19 @@ def get_top_docs(
231
237
 
232
238
  def _select_docs(docs, theta, topic_id: int):
233
239
  probs = theta[topic_id, :]
234
- idx = argsort(probs)[:-docs_num-1:-1]
240
+ idx = argsort(probs)[: -docs_num - 1 : -1]
235
241
  result = Series(list(map(lambda x: docs[x], idx)))
236
- result.name = f'topic{topic_id}'
242
+ result.name = f"topic{topic_id}"
237
243
  return result
238
244
 
239
245
  topics_num = theta.shape[0]
240
246
  topics_idx = arange(topics_num) if topics is None else topics
241
- return concat(
242
- map(lambda x: _select_docs(docs, theta, x), topics_idx), axis=1)
247
+ return concat(map(lambda x: _select_docs(docs, theta, x), topics_idx), axis=1)
243
248
 
244
249
 
245
250
  def calc_topics_marg_probs(
246
- theta: Union[DataFrame, ndarray],
247
- topic_id: int = None) -> Union[DataFrame, ndarray]:
251
+ theta: Union[DataFrame, ndarray], topic_id: Optional[int] = None
252
+ ) -> ndarray:
248
253
  """Calculate marginal topics probabilities.
249
254
 
250
255
  Parameters
@@ -259,18 +264,18 @@ def calc_topics_marg_probs(
259
264
  Union[pandas.DataFrame, numpy.ndarray]
260
265
  Marginal topics probabilities.
261
266
  """
267
+ p_t = array(theta).sum(axis=1)
268
+ p_t /= p_t.sum()
262
269
  if topic_id is not None:
263
- if isinstance(theta, ndarray):
264
- return theta[topic_id, :].sum()
265
- if isinstance(theta, DataFrame):
266
- return theta.iloc[topic_id, :].sum()
267
-
268
- return theta.sum(axis=1)
270
+ return p_t[topic_id]
271
+ return p_t
269
272
 
270
273
 
271
274
  def calc_terms_marg_probs(
272
- phi: Union[ndarray, DataFrame],
273
- word_id: Optional[int] = None) -> Union[ndarray, Series]:
275
+ phi: Union[ndarray, DataFrame],
276
+ p_t: Union[ndarray, Series],
277
+ word_id: Optional[int] = None,
278
+ ) -> ndarray:
274
279
  """Calculate marginal terms probabilities.
275
280
 
276
281
  Parameters
@@ -285,19 +290,13 @@ def calc_terms_marg_probs(
285
290
  Union[numpy.ndarray, pandas.Series]
286
291
  Marginal terms probabilities.
287
292
  """
293
+ p_w = (array(phi) * array(p_t)).sum(axis=1)
288
294
  if word_id is not None:
289
- if isinstance(phi, ndarray):
290
- return phi[word_id, :].sum()
291
- if isinstance(phi, DataFrame):
292
- return phi.iloc[word_id, :].sum()
293
-
294
- return phi.sum(axis=1)
295
+ return p_w[word_id]
296
+ return p_w
295
297
 
296
298
 
297
- def get_salient_terms(
298
- terms_freqs: ndarray,
299
- phi: ndarray,
300
- theta: ndarray) -> ndarray:
299
+ def get_salient_terms(phi: ndarray, theta: ndarray) -> ndarray:
301
300
  """Get salient terms.
302
301
 
303
302
  Calculated as:
@@ -306,8 +305,6 @@ def get_salient_terms(
306
305
 
307
306
  Parameters
308
307
  ----------
309
- terms_freqs : numpy.ndarray
310
- Words frequencies.
311
308
  phi : numpy.ndarray
312
309
  Words vs topics matrix.
313
310
  theta : numpy.ndarray
@@ -318,18 +315,24 @@ def get_salient_terms(
318
315
  numpy.ndarray
319
316
  Terms saliency values.
320
317
  """
321
- p_t = array(calc_topics_marg_probs(theta))
322
- p_w = array(calc_terms_marg_probs(phi))
318
+ p_t = calc_topics_marg_probs(theta)
319
+ p_w = calc_terms_marg_probs(phi, p_t)
323
320
 
324
321
  def _p_tw(phi, w, t):
325
- return phi[w, t] * p_t[t] / p_w[w]
326
-
327
- saliency = array((
328
- terms_freqs[w] * sum((
329
- _p_tw(phi, w, t) * log(_p_tw(phi, w, t) / p_t[t])
330
- for t in range(phi.shape[1])))
331
- for w in range(phi.shape[0])
332
- ))
322
+ return array(phi)[w, t] * p_t[t] / p_w[w]
323
+
324
+ saliency = array(
325
+ [
326
+ p_w[w]
327
+ * sum(
328
+ (
329
+ _p_tw(phi, w, t) * log(_p_tw(phi, w, t) / p_t[t])
330
+ for t in range(phi.shape[1])
331
+ )
332
+ )
333
+ for w in range(phi.shape[0])
334
+ ]
335
+ )
333
336
  # saliency(term w) = frequency(w)
334
337
  # * [sum_t p(t | w) * log(p(t | w)/p(t))] for topics t
335
338
  # p(t | w) = p(w | t) * p(t) / p(w)
@@ -337,10 +340,8 @@ def get_salient_terms(
337
340
 
338
341
 
339
342
  def calc_terms_probs_ratio(
340
- phi: DataFrame,
341
- topic: int,
342
- terms_num: int = 30,
343
- lambda_: float = 0.6) -> DataFrame:
343
+ phi: DataFrame, topic: int, terms_num: int = 30, lambda_: float = 0.6
344
+ ) -> DataFrame:
344
345
  """Get terms conditional and marginal probabilities.
345
346
 
346
347
  Parameters
@@ -368,35 +369,38 @@ def calc_terms_probs_ratio(
368
369
  pandas.DataFrame
369
370
  Words conditional and marginal probabilities.
370
371
  """
371
- p_cond_name = 'Conditional term probability, p(w | t)'
372
- p_cond = phi.iloc[:, topic]\
373
- .rename(p_cond_name)\
374
- if isinstance(phi, DataFrame)\
372
+ p_cond_name = "Conditional term probability, p(w | t)"
373
+ p_cond = (
374
+ phi.iloc[:, topic].rename(p_cond_name)
375
+ if isinstance(phi, DataFrame)
375
376
  else Series(phi[:, topic], name=p_cond_name)
377
+ )
376
378
 
377
- p_marg_name = 'Marginal term probability, p(w)'
378
- p_marg = phi.sum(axis=1)\
379
- .rename(p_marg_name)\
380
- if isinstance(phi, DataFrame)\
379
+ p_marg_name = "Marginal term probability, p(w)"
380
+ p_marg = (
381
+ phi.sum(axis=1).rename(p_marg_name)
382
+ if isinstance(phi, DataFrame)
381
383
  else Series(phi[:, topic], name=p_marg_name)
384
+ )
382
385
 
383
386
  terms_probs = concat((p_marg, p_cond), axis=1)
384
387
  relevant_idx = get_relevant_terms(phi, topic, lambda_).index
385
388
  terms_probs_slice = terms_probs.loc[relevant_idx].head(terms_num)
386
389
 
387
- return terms_probs_slice\
388
- .reset_index(drop=False)\
390
+ return (
391
+ terms_probs_slice.reset_index(drop=False)
389
392
  .melt(
390
393
  id_vars=[terms_probs_slice.index.name],
391
- var_name='Type',
392
- value_name='Probability')\
393
- .rename(columns={terms_probs_slice.index.name: 'Terms'})
394
+ var_name="Type",
395
+ value_name="Probability",
396
+ )
397
+ .rename(columns={terms_probs_slice.index.name: "Terms"})
398
+ )
394
399
 
395
400
 
396
401
  def get_relevant_terms(
397
- phi: Union[ndarray, DataFrame],
398
- topic: int,
399
- lambda_: float = 0.6) -> Series:
402
+ phi: Union[ndarray, DataFrame], topic: int, lambda_: float = 0.6
403
+ ) -> Series:
400
404
  """Select relevant terms.
401
405
 
402
406
  Parameters
@@ -422,11 +426,10 @@ def get_relevant_terms(
422
426
  pandas.Series
423
427
  Terms sorted by relevance (descendingly).
424
428
  """
425
- phi_topic = phi.iloc[:, topic]\
426
- if isinstance(phi, DataFrame)\
427
- else phi[:, topic]
429
+ phi_topic = phi.iloc[:, topic] if isinstance(phi, DataFrame) else phi[:, topic]
428
430
 
429
431
  # relevance = lambda * log(p(w | t)) + (1 - lambda) * log(p(w | t) / p(w))
430
- relevance = lambda_ * nplog(phi_topic)\
431
- + (1 - lambda_) * nplog(phi_topic / phi.sum(axis=1))
432
+ relevance = lambda_ * nplog(phi_topic) + (1 - lambda_) * nplog(
433
+ phi_topic / phi.sum(axis=1)
434
+ )
432
435
  return relevance.sort_values(ascending=False)