Dans cet article, j'aimerais jeter un œil au contenu de sklearn. Récemment, de nombreux livres ont été publiés pour vous permettre de mettre en œuvre vous-même des algorithmes d'apprentissage automatique. Je ne l'ai pas lu moi-même, mais je crois que si vous regardez de plus près le contenu de sklearn sans lire ce livre, vous vous y habituerez pour pouvoir le mettre en œuvre vous-même sans acheter de livre. De plus, sklearn est un package gratuit qui est édité quotidiennement par un grand nombre d'utilisateurs, de sorte que le programme est merveilleusement optimisé. C'est donc un programme très poli et il n'y a aucune raison de ne pas l'utiliser pour étudier le programme! !! Cela dit, même si un débutant regarde soudainement le contenu de sklearn, je pense que c'est vrai qu'il ne peut pas le comprendre. Même si je regardais le contenu de sklearn, je ne pouvais pas l'organiser dans mon esprit. Alors, y a-t-il quelqu'un qui peut expliquer le contenu du paquet sklearn? Quand. .. .. .. Ce que je pensais ne figurait pas parmi les bons. Donc, j'ai pensé que je devrais trouver du temps libre et jeter un œil au contenu. !! Je ne vais pas l'expliquer si soigneusement, mais je vais juste jeter un coup d'œil rapide. Comme point de départ, examinons le contenu d'un simple CountVectorizer.
CountVectorizer CountVectorizer est un algorithme qui compte la fréquence d'apparition des mots. La fréquence d'apparition des mots compte le nombre de fois qu'un mot apparaît dans une phrase et est utilisé, et peut être facilement calculée à l'aide du vecteur de décompte de sklearn. La méthode de détermination de la fréquence d'apparition utilise une méthode appelée extraction de quantité de caractéristiques. L'extraction de caractéristiques est une vectorisation des caractéristiques des données d'entraînement, et dans ce cas, la fréquence d'occurrence des mots correspond au vecteur (valeur numérique) quote % E3% 81% AEcountvectorizer% E3% 82% 92% E7% 94% A8% E3% 81% 84% E3% 81% A6% E5% 8D% 98% E8% AA% 9E% E3% 81% AE% E5 % 87% BA% E7% 8F% BE% E9% A0% BB% E5% BA% A6% E3% 82% 92% E6% 95% B0% E3% 81% 88% E3% 81% A6% E3% 81 % BF% E3% 82% 8B /).
class CountVectorizer(_VectorizerMixin, BaseEstimator):
def __init__(self, input='content', encoding='utf-8',
decode_error='strict', strip_accents=None,
lowercase=True, preprocessor=None, tokenizer=None,
stop_words=None, token_pattern=r"(?u)\b\w\w+\b",
ngram_range=(1, 1), analyzer='word',
max_df=1.0, min_df=1, max_features=None,
vocabulary=None, binary=False, dtype=np.int64):
self.input = input
self.encoding = encoding
self.decode_error = decode_error
self.strip_accents = strip_accents
self.preprocessor = preprocessor
self.tokenizer = tokenizer
self.analyzer = analyzer
self.lowercase = lowercase
self.token_pattern = token_pattern
self.stop_words = stop_words
self.max_df = max_df
self.min_df = min_df
if max_df < 0 or min_df < 0:
raise ValueError("negative value for max_df or min_df")
self.max_features = max_features
if max_features is not None:
if (not isinstance(max_features, numbers.Integral) or
max_features <= 0):
raise ValueError(
"max_features=%r, neither a positive integer nor None"
% max_features)
self.ngram_range = ngram_range
self.vocabulary = vocabulary
self.binary = binary
self.dtype = dtype
Ça ressemble à ça. Cet objet semble hériter de deux classes, mais fondamentalement fit et fit_transform suffisent pour l'utiliser. De plus, lorsque l'on regarde les valeurs initiales, il semble n'y avoir aucun paramètre requis. Regardons maintenant l'ajustement en premier.
def fit(self, raw_documents, y=None):
"""Learn a vocabulary dictionary of all tokens in the raw documents.
Parameters
----------
raw_documents : iterable
An iterable which yields either str, unicode or file objects.
Returns
-------
self
"""
self._warn_for_unused_params() ##préoccupation
self.fit_transform(raw_documents)
return self
Fait intéressant, il semble que fit_transform soit utilisé dans fit. Il s'avère que ce n'est pas fit, etc. qui est important, mais fit_transform. Jetons également un coup d'œil à celui ci-dessus.
def _warn_for_unused_params(self):
if self.tokenizer is not None and self.token_pattern is not None:
warnings.warn("The parameter 'token_pattern' will not be used"
" since 'tokenizer' is not None'")
if self.preprocessor is not None and callable(self.analyzer):
warnings.warn("The parameter 'preprocessor' will not be used"
" since 'analyzer' is callable'")
if (self.ngram_range != (1, 1) and self.ngram_range is not None
and callable(self.analyzer)):
warnings.warn("The parameter 'ngram_range' will not be used"
" since 'analyzer' is callable'")
if self.analyzer != 'word' or callable(self.analyzer):
if self.stop_words is not None:
warnings.warn("The parameter 'stop_words' will not be used"
" since 'analyzer' != 'word'")
if self.token_pattern is not None and \
self.token_pattern != r"(?u)\b\w\w+\b":
warnings.warn("The parameter 'token_pattern' will not be used"
" since 'analyzer' != 'word'")
if self.tokenizer is not None:
warnings.warn("The parameter 'tokenizer' will not be used"
" since 'analyzer' != 'word'")
Autant que je puisse voir, il semble que je cherche quelque chose qui ne va pas avec les paramètres. L'important ici est que la méthode ici n'est pas un CountVectorizer, mais un objet de _VectorizerMixin. Il semble donc que cet objet effectue une vérification d'erreur pour les paramètres et plus encore. De plus, lors de l'héritage de plusieurs objets, ajoutez Mixin à la fin comme _VectorizerMixin. Les objets avec ceci sont essentiellement utilisés en combinaison avec d'autres objets! !! Cela indique cela. Voyons maintenant l'importante méthode fit_transform.
def fit_transform(self, raw_documents, y=None):
if isinstance(raw_documents, str): #Raw ici_Exclut les cas où les documents n'apparaissent pas dans le type de liste. type str inutile! !!
raise ValueError(
"Iterable over raw text documents expected, "
"string object received.")
self._validate_params() #n_Si la gamme de grammes convient
self._validate_vocabulary()#préoccupation
max_df = self.max_df #Ceci est un petit point. Puisqu'il est difficile de se décrire plusieurs fois, nous l'utilisons ici comme variable.
min_df = self.min_df
max_features = self.max_features
vocabulary, X = self._count_vocab(raw_documents,
self.fixed_vocabulary_) #préoccupation
if self.binary:
X.data.fill(1)
if not self.fixed_vocabulary_:
X = self._sort_features(X, vocabulary)
n_doc = X.shape[0]
max_doc_count = (max_df
if isinstance(max_df, numbers.Integral)
else max_df * n_doc)
min_doc_count = (min_df
if isinstance(min_df, numbers.Integral)
else min_df * n_doc)
if max_doc_count < min_doc_count:
raise ValueError(
"max_df corresponds to < documents than min_df")
X, self.stop_words_ = self._limit_features(X, vocabulary,
max_doc_count,
min_doc_count,
max_features)
self.vocabulary_ = vocabulary
return X #Renvoie un vecteur
Jetons un coup d'œil au premier point, la méthode de self._validate_vocabulary ().
def _validate_vocabulary(self):
vocabulary = self.vocabulary #dictionnaire
if vocabulary is not None: #Le dictionnaire est-il entré comme valeur initiale?#Lorsque le dictionnaire n'est pas défini. Ou ceci est exécuté lors du montage une fois
if isinstance(vocabulary, set):
vocabulary = sorted(vocabulary)
if not isinstance(vocabulary, Mapping): #Le vocabulaire est-il correctement de type dict? Fait l'objet d'une enquête.
vocab = {}
for i, t in enumerate(vocabulary):
if vocab.setdefault(t, i) != i: #Vérifiez ici les expressions en double dans le dictionnaire
msg = "Duplicate term in vocabulary: %r" % t
raise ValueError(msg)
vocabulary = vocab
else:#Votre dictionnaire n'est pas de type dict, mais est-ce correct? ??
indices = set(vocabulary.values())
if len(indices) != len(vocabulary):
raise ValueError("Vocabulary contains repeated indices.")
for i in range(len(vocabulary)):
if i not in indices:
msg = ("Vocabulary of size %d doesn't contain index "
"%d." % (len(vocabulary), i))
raise ValueError(msg)
if not vocabulary:
raise ValueError("empty vocabulary passed to fit")
self.fixed_vocabulary_ = True #Le dictionnaire est correctement défini
self.vocabulary_ = dict(vocabulary) #Formez un dictionnaire.
else: #Lorsque le dictionnaire n'est pas entré dans les paramètres initiaux.
self.fixed_vocabulary_ = False #Le dictionnaire n'est pas défini.
Cette méthode est une méthode de vectorizerMixin. Cette méthode forme-t-elle essentiellement un dictionnaire? ?? Cela semble être une méthode pour vérifier. La création d'un dictionnaire est un élément important qui correspond à la colonne de sortie. Si aucun dictionnaire n'est créé pour les paramètres initiaux, self.fixed_vocabulary = False est exécuté. Cette méthode est en fait appelée la deuxième fois, c'est-à-dire lorsqu'elle est transformée. Par conséquent, self.fixed_vocabulary_ = True self.vocabulary_ = dict (vocabulaire) Ces deux sont exécutés.
Maintenant que nous avons confirmé que le dictionnaire a été créé, vérifions self.count_vocab (raw_documents, self.fixed_vocabulary).
def _count_vocab(self, raw_documents, fixed_vocab):
"""Create sparse feature matrix, and vocabulary where fixed_vocab=False
"""
if fixed_vocab:#Lorsque le dictionnaire est créé
vocabulary = self.vocabulary_
else:#Lorsque le dictionnaire n'a pas été créé
# Add a new value when a new vocabulary item is seen
vocabulary = defaultdict()
vocabulary.default_factory = vocabulary.__len__ #En faisant ces réglages, le vocabulaire[mot]とすることでそのmotに自動でindexが設定されます.結構役たちます.
analyze = self.build_analyzer() #Ici n_Des paramètres tels que le gramme sont applicables.
j_indices = []
indptr = []
values = _make_int_array()
indptr.append(0)
for doc in raw_documents:#Lisez des données unidimensionnelles.
#doc = ["hoge hogeee hogeeeee"]Se sentir comme
feature_counter = {}
for feature in analyze(doc):#mot
#feature = "hoge"Se sentir comme
try:
feature_idx = vocabulary[feature] #Ici hoge:1 hogee:2 hogeee:C'est comme 3. fonctionnalité_idx est une donnée numérique. Si c'est hoge, 1 est changé.
if feature_idx not in feature_counter:
feature_counter[feature_idx] = 1 #feature_Si ce n'est pas dans le dictionnaire du compteur.
else:
feature_counter[feature_idx] += 1 #feature_Si c'est dans le dictionnaire du compteur+1 être
except KeyError:
# Ignore out-of-vocabulary items for fixed_vocab=True
continue
j_indices.extend(feature_counter.keys()) #Mots du dictionnaire (numérique)
values.extend(feature_counter.values()) #Combien de fois un mot du dictionnaire apparaît
indptr.append(len(j_indices))
#Les trois méthodes ci-dessus sont les méthodes qui apparaissent lors de la création d'un modèle fragmenté.
if not fixed_vocab: #Exécuter lorsque le dictionnaire n'a pas été créé
# disable defaultdict behaviour
vocabulary = dict(vocabulary)
if not vocabulary:
raise ValueError("empty vocabulary; perhaps the documents only"
" contain stop words")
if indptr[-1] > np.iinfo(np.int32).max: # = 2**31 - 1
if _IS_32BIT:
raise ValueError(('sparse CSR array has {} non-zero '
'elements and requires 64 bit indexing, '
'which is unsupported with 32 bit Python.')
.format(indptr[-1]))
indices_dtype = np.int64
else:
indices_dtype = np.int32
j_indices = np.asarray(j_indices, dtype=indices_dtype)
indptr = np.asarray(indptr, dtype=indices_dtype)
values = np.frombuffer(values, dtype=np.intc)
X = sp.csr_matrix((values, j_indices, indptr),
shape=(len(indptr) - 1, len(vocabulary)),
dtype=self.dtype)
X.sort_indices()
return vocabulary, X #Dictionnaire et X(Valeur vectorielle de clairsemée)
Je pense que beaucoup de gens connaissent les algorithmes utilisés pour créer des dictionnaires ici. Ce que vous faites n'est pas si difficile. Cependant, utiliser la valeur éparse est un peu compliqué.
Eh bien, c'est la dernière étape.
if not self.fixed_vocabulary_: #Exécuter lorsque False
X = self._sort_features(X, vocabulary) #Réorganisez le dictionnaire proprement.
n_doc = X.shape[0]
max_doc_count = (max_df
if isinstance(max_df, numbers.Integral)
else max_df * n_doc)
min_doc_count = (min_df
if isinstance(min_df, numbers.Integral)
else min_df * n_doc)
if max_doc_count < min_doc_count:
raise ValueError(
"max_df corresponds to < documents than min_df")
X, self.stop_words_ = self._limit_features(X, vocabulary,
max_doc_count,
min_doc_count,
max_features)
self.vocabulary_ = vocabulary #Définir le dictionnaire ici
return X
Ce qui précède est fondamentalement étrange si min_doc_count <min_doc_count! Dans self._limit_features (), la dimension est réduite en fonction de la fréquence d'apparition. return X renvoie le vecteur avec scipy.
J'ai jeté un coup d'œil au contenu de Count Vectorizer dans sklearn. Le programme n'était pas si compliqué car aucune formule n'est apparue cette fois. Si vous le divisez en parties inattendues, chaque processus est simple. Jetez un œil à cet article et voyez comment il est fabriqué par vous-même. Ensuite, je pense que je vais essayer TF-IDF. Je l'écrirai quand j'en aurai envie. c'est tout
Recommended Posts