[PYTHON] Ich habe mir den Inhalt von sklearn (scikit-learn) angesehen. (1) ~ Was ist mit der Implementierung von CountVectorizer? ~

Einführung

In diesem Artikel möchte ich einen Blick auf den Inhalt von sklearn werfen. In letzter Zeit wurden viele Bücher veröffentlicht, in denen Sie versuchen können, Algorithmen für maschinelles Lernen selbst zu implementieren. Ich habe es selbst nicht gelesen, aber ich glaube, wenn Sie sich den Inhalt von sklearn genauer ansehen, ohne dieses Buch zu lesen, werden Sie sich daran gewöhnen, damit Sie es selbst implementieren können, ohne ein Buch zu kaufen. Außerdem ist sklearn ein kostenloses Paket, das täglich von einer großen Anzahl von Benutzern bearbeitet wird, sodass das Programm wunderbar optimiert ist. Es ist also ein sehr höfliches Programm und es gibt keinen Grund, es nicht zum Studieren des Programms zu verwenden! !! Das heißt, selbst wenn ein Anfänger plötzlich den Inhalt von sklearn betrachtet, denke ich, dass es wahr ist, dass er es nicht verstehen kann. Selbst wenn ich mir den Inhalt von sklearn ansah, konnte ich ihn nicht in meinem Kopf organisieren. Gibt es also jemanden, der den Inhalt des sklearn-Pakets erklären kann? Wann. .. .. .. Was ich dachte, erschien nicht unter den Guten. Also dachte ich, ich sollte etwas Freizeit finden und mir den Inhalt ansehen. !! Ich werde es nicht so sorgfältig erklären, aber ich werde nur einen kurzen Blick darauf werfen. Schauen wir uns zunächst den Inhalt eines einfachen CountVectorizers an.

CountVectorizer CountVectorizer ist ein Algorithmus, der die Häufigkeit des Auftretens von Wörtern zählt. Die Häufigkeit des Auftretens von Wörtern zählt, wie oft ein Wort in einem Satz vorkommt und verwendet wird, und kann mit dem Count Vectorizer von sklearn einfach berechnet werden. Eine Methode, die als Merkmalmengenextraktion bezeichnet wird, wird verwendet, um die Häufigkeit des Auftretens zu bestimmen. Die Merkmalsextraktion ist eine Vektorisierung der Merkmale der Trainingsdaten. In diesem Fall entspricht die Häufigkeit des Auftretens von Wörtern dem Vektor (numerischer Wert) Zitat. % 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 /).

Lass uns einen Blick darauf werfen.

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

Es scheint so. Dieses Objekt scheint zwei Klassen zu erben, aber im Grunde sind fit und fit_transform ausreichend, wenn dies tatsächlich verwendet wird. Wenn man sich die Anfangswerte ansieht, scheint es auch keine erforderlichen Parameter zu geben. Schauen wir uns jetzt zuerst die Passform an.

    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() ##Besorgnis, Sorge
        self.fit_transform(raw_documents)
        return self

Interessanterweise scheint fit_transform in fit verwendet zu werden. Es stellt sich heraus, dass es nicht auf Fit usw. ankommt, sondern auf fit_transform. Schauen wir uns auch den obigen an.

    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'")

Soweit ich sehen kann, scheint es, dass ich nach etwas suche, das mit den Parametern nicht stimmt. Wichtig hierbei ist, dass die Methode hier kein CountVectorizer ist, sondern ein Objekt von _VectorizerMixin. Es scheint also, dass dieses Objekt Fehler auf Parameter und mehr überprüft. Wenn Sie mehrere Objekte erben, fügen Sie am Ende Mixin wie _VectorizerMixin hinzu. Objekte mit diesem werden grundsätzlich in Kombination mit anderen Objekten verwendet! !! Es weist darauf hin. Überprüfen wir nun die wichtige Methode fit_transform.

    def fit_transform(self, raw_documents, y=None):

        if isinstance(raw_documents, str):  #Roh hier_Schließt Fälle aus, in denen Dokumente nicht im Listentyp angezeigt werden. str Typ nutzlos! !!
            raise ValueError(
                "Iterable over raw text documents expected, "
                "string object received.")

        self._validate_params() #n_Ob der Grammbereich geeignet ist
        self._validate_vocabulary()#Besorgnis, Sorge
        max_df = self.max_df #Das ist ein kleiner Punkt. Da es schwierig ist, sich selbst oft zu beschreiben, verwenden wir es hier als Variable.
        min_df = self.min_df
        max_features = self.max_features

        vocabulary, X = self._count_vocab(raw_documents,
                                          self.fixed_vocabulary_) #Besorgnis, Sorge
 
        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 #Gibt einen Vektor zurück


Schauen wir uns den ersten Punkt an, die Methode von self._validate_vocabulary ().

    def _validate_vocabulary(self):
        vocabulary = self.vocabulary #Wörterbuch
        if vocabulary is not None: #Wird das Wörterbuch als Anfangswert eingegeben?#Wenn das Wörterbuch nicht eingestellt ist. Oder dies wird beim einmaligen Anpassen ausgeführt
            if isinstance(vocabulary, set): 
                vocabulary = sorted(vocabulary)
            if not isinstance(vocabulary, Mapping): #Ist der Wortschatz richtig diktiert? Wird untersucht.
                vocab = {}
                for i, t in enumerate(vocabulary):
                    if vocab.setdefault(t, i) != i: #Suchen Sie hier nach doppelten Ausdrücken im Wörterbuch
                        msg = "Duplicate term in vocabulary: %r" % t
                        raise ValueError(msg)
                vocabulary = vocab
            else:#Ihr Wörterbuch ist kein Diktattyp, aber ist es in Ordnung? ??
                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 #Das Wörterbuch ist richtig eingestellt
            self.vocabulary_ = dict(vocabulary) #Bilden Sie ein Wörterbuch.
        else: #Wenn das Wörterbuch nicht in den Anfangsparametern eingegeben wird.
            self.fixed_vocabulary_ = False #Das Wörterbuch ist nicht festgelegt.

Diese Methode ist eine Methode von vectorizerMixin. Bildet diese Methode im Grunde genommen ein Wörterbuch? ?? Es scheint eine Methode zu sein, um zu überprüfen. Das Erstellen eines Wörterbuchs ist ein wichtiges Element, das der Ausgabespalte entspricht. Wenn für die Anfangsparameter kein Wörterbuch erstellt wird, wird self.fixed_vocabulary = False ausgeführt. Diese Methode wird tatsächlich zum zweiten Mal aufgerufen, dh wenn sie transformiert wird. Daher ist self.fixed_vocabulary_ = True self.vocabulary_ = dict (Vokabular) Diese beiden werden ausgeführt.

Nachdem wir bestätigt haben, dass das Wörterbuch erstellt wurde, überprüfen wir 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:#Wenn das Wörterbuch erstellt wird
            vocabulary = self.vocabulary_
        else:#Wenn das Wörterbuch nicht erstellt wurde
            # Add a new value when a new vocabulary item is seen
            vocabulary = defaultdict()
            vocabulary.default_factory = vocabulary.__len__ #Durch diese Einstellungen wird der Wortschatz[Wort]とすることでそのWortに自動でindexが設定されます.結構役たちます.

        analyze = self.build_analyzer() #Hier n_Einstellungen wie Gramm sind anwendbar.
        j_indices = []
        indptr = []

        values = _make_int_array()
        indptr.append(0)
        for doc in raw_documents:#Lesen Sie eindimensionale Daten.
            #doc = ["hoge hogeee hogeeeee"]Fühle mich wie
            feature_counter = {}
            for feature in analyze(doc):#Wort
                #feature = "hoge"Fühle mich wie
                try:
                    feature_idx = vocabulary[feature] #Hier hoge:1 hogee:2 hogeee:Es fühlt sich an wie 3. Merkmal_idx sind numerische Daten. Wenn es hoge ist, wird 1 geändert.
                    if feature_idx not in feature_counter:
                        feature_counter[feature_idx] = 1 #feature_Wenn es nicht im Zählerwörterbuch ist.
                    else:
                        feature_counter[feature_idx] += 1 #feature_Wenn es im Zählerwörterbuch steht+1 zu sein
                except KeyError:
                    # Ignore out-of-vocabulary items for fixed_vocab=True
                    continue

            j_indices.extend(feature_counter.keys()) #Wörterbuchwörter (numerisch)
            values.extend(feature_counter.values()) #Wie oft erscheint ein Wort im Wörterbuch?
            indptr.append(len(j_indices)) 
            #Die obigen drei Methoden werden beim Erstellen eines Modells mit geringer Dichte angezeigt.

        if not fixed_vocab: #Ausführen, wenn das Wörterbuch nicht erstellt wurde
            # 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 #Wörterbuch und X.(Vektorwert von spärlich)

Ich denke, viele Leute sind mit den Algorithmen vertraut, mit denen hier Wörterbücher erstellt werden. Was Sie tun, ist nicht so schwierig. Die Verwendung des Sparse-Werts ist jedoch etwas kompliziert.

Nun, es ist die letzte Phase.

        if not self.fixed_vocabulary_: #Ausführen, wenn False
            X = self._sort_features(X, vocabulary) #Ordnen Sie das Wörterbuch ordentlich neu an.

            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 #Stellen Sie hier das Wörterbuch ein

        return X

Das obige ist grundsätzlich seltsam, wenn min_doc_count <min_doc_count! In self._limit_features () wird die Dimension entsprechend der Häufigkeit des Auftretens reduziert. return X gibt den Vektor mit scipy zurück.

Am Ende

Ich habe mir den Inhalt von Count Vectorizer in sklearn angesehen. Das Programm war nicht so kompliziert, da diesmal keine Formeln erschienen. Wenn Sie es in unerwartete Teile unterteilen, ist jeder Prozess einfach. Schauen Sie sich diesen Artikel an und sehen Sie, wie er selbst hergestellt wurde. Als nächstes werde ich TF-IDF ausprobieren. Ich werde es schreiben, wenn ich Lust dazu habe. das ist alles

Recommended Posts

Ich habe mir den Inhalt von sklearn (scikit-learn) angesehen. (1) ~ Was ist mit der Implementierung von CountVectorizer? ~
Eine verschiedene Zusammenfassung dessen, was ich über Ansible recherchiert habe
Ein Memorandum über die Umsetzung von Empfehlungen in Python
Werfen wir einen Blick auf die Feature-Map von YOLO v3
Ich habe mir genauer angesehen, warum Python selbst benötigt wird
Ich brachte AI dazu, über die Texte von Genshi Yonezu nachzudenken (Implementierung)
Ich habe den Inhalt des Docker-Volumes überprüft
Ich habe einen Benchmark für die h5py-Komprimierung erstellt
Die Geschichte der IPv6-Adresse, die ich auf ein Minimum beschränken möchte
Ich habe die Implementierung von range gelesen (Objects / rangeobject.c)
Über die Verarbeitungsgeschwindigkeit von SVM (SVC) von Scikit-Learn
Schreiben Sie eine Notiz über die Python-Version von Python Virtualenv
Über die Entwicklungsinhalte des maschinellen Lernens (Beispiel)
Woran ich in der Aufnahmeprüfungsfrage "Bayes Statistics from the Basics" gedacht habe
Ich dachte darüber nach, warum Python selbst mit dem Gefühl eines Python-Interpreters notwendig ist
Ein Memorandum über Warnungen in Pylint-Ausgabeergebnissen
[GoLang] Setzen Sie am Anfang des Kommentars ein Leerzeichen
Werfen Sie einen Blick auf die Verarbeitung von LightGBM Tuner
Python-Implementierung der Bayes'schen linearen Regressionsklasse
Schauen Sie sich die Go-Punktzahl eines professionellen Go-Spielers an
Ich verfolgte die Implementierung des Befehls du (zweite Hälfte)
Eine Zusammenfassung dessen, was ich wie ein Blog berührt habe
Aufgaben zu Beginn eines neuen Python-Projekts
Was ist ein empfohlener Motor? Zusammenfassung der Typen
Schauen Sie sich das Kaggle / Titanic-Tutorial genauer an
Ich habe nach dem Inhalt von CloudWatch Logs Agent gesucht
Ich habe ein Tool erstellt, um die Antwortlinks von OpenAI Gym auf einmal zu erhalten
Über den Inhalt von wscript beim Erstellen einer solchen D-Sprachumgebung mit Waf
Was ich dachte, nachdem ich ein Jahr lang an dem Projekt "Schreibe keine Kommentare" gearbeitet hatte
Verändert TensorFlow das Bild des tiefen Lernens? Was ich dachte, nachdem ich ein wenig berührt hatte