Apprenez des documents d'apprentissage automatique (DeepLeaning4j) en Java et essayez d'extraire des mots fortement liés à un mot spécifique

Choses à faire

[Article Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%82%A4%E3 % 83% B3% E3% 83% 91% E3% 82% AF% E3% 83% 88_ (% E7% AB% B6% E8% B5% B0% E9% A6% AC)) comme données d'entraînement Extrayez des mots (noms et verbes) qui sont fortement liés à «impact profond».

point

Texte à préparer à l'avance

[Ici](https://ja.wikipedia.org/wiki/%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%82%A4%E3%83 Collez le texte de manière appropriée à partir de% B3% E3% 83% 91% E3% 82% AF% E3% 83% 88_ (% E7% AB% B6% E8% B5% B0% E9% A6% AC) Enregistrez en UTF-8.

la mise en oeuvre

C'est facile, donc à Maven

pom.xml


(réduction)

    <repositories>    
        <repository>
            <id>ATILIKA dependencies</id>
            <url>http://www.atilika.org/nexus/content/repositories/atilika</url>
        </repository>    
    </repositories>

(Omission)
        <dependency>
            <artifactId>lucene-core</artifactId>
            <groupId>org.apache.lucene</groupId>
            <version>5.1.0</version>
        </dependency>        
        <dependency>
            <artifactId>lucene-analyzers-kuromoji</artifactId>
            <groupId>org.apache.lucene</groupId>
            <version>5.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.deeplearning4j</groupId>
            <artifactId>deeplearning4j-ui</artifactId>
            <version>0.5.0</version>
        </dependency>

        <dependency>
            <groupId>org.deeplearning4j</groupId>
            <artifactId>deeplearning4j-nlp</artifactId>
            <version>0.5.0</version>
        </dependency>

        <dependency>
            <groupId>org.nd4j</groupId>
            <artifactId>nd4j-native</artifactId>
            <version>0.5.0</version>
        </dependency>    

        <dependency>
            <groupId>org.atilika.kuromoji</groupId>
            <artifactId>kuromoji</artifactId>
            <version>0.7.7</version>
            <type>jar</type>
        </dependency>

Enveloppez le Tokenizer de Kuromoji

Dans l'état actuel des choses, seul l'anglais peut analyser la morphologie, le kuromoji peut donc être utilisé. Ici a été très utile. Ou plutôt, presque tel quel. Cependant, certaines modifications ont été apportées.

KuromojiIpadicTokenizer.java



/**
 *Parce qu'une analyse morphologique japonaise est nécessaire
 *Enveloppez le Tokenizer de Kuromoji dans l'interface Tokneizer de dl4j
 * @author 
 */
public class KuromojiIpadicTokenizer implements Tokenizer{
    private List<Token> tokens;
    private int index;
    private TokenPreProcess preProcess;

    /**
     *Le dictionnaire ne fonctionne tout simplement pas ...
     *Pour le moment, réglez Mode sur Recherche pour qu'il se sente relativement bien.
     */
    public KuromojiIpadicTokenizer (String toTokenize) {
      
        try{
            org.atilika.kuromoji.Tokenizer tokenizer 
                = org.atilika.kuromoji.Tokenizer.builder()
                    .userDictionary("D:\\deepleaning\\mydic.txt")
                    .mode(org.atilika.kuromoji.Tokenizer.Mode.SEARCH)
                    .build();
            tokens = tokenizer.tokenize(toTokenize);
            index = (tokens.isEmpty()) ? -1:0;
        } catch (IOException ex) {
            Logger.getLogger(KuromojiIpadicTokenizer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }


    @Override
    public int countTokens() {
        return tokens.size();
    }

    @Override
    public List<String> getTokens() {
        List<String> ret = new ArrayList<String>();
        while (hasMoreTokens()) {
            ret.add(nextToken());
        }
        return ret;
    }

    @Override
    public boolean hasMoreTokens() {
        if (index < 0)
            return false;
        else
            return index < tokens.size();
    }

    /**
     *Focus sur les mots liés à la nomenclature et aux verbes (forme de base)
     *Une nomenclature personnalisée peut être nécessaire si le dictionnaire utilisateur de kuromoji fonctionne
     *Déposez les autres pièces dans des espaces de demi-largeur pour éviter l'analyse
     * @return 
     */
    @Override
    public String nextToken() {
        if (index < 0)
        return null;

        Token tok = tokens.get(index);
        index++;
        if(!tok.getPartOfSpeech().startsWith("nom") 
            && !tok.getPartOfSpeech().startsWith("verbe")
            && !tok.getPartOfSpeech().startsWith("Nomenclature personnalisée")){
            return " ";
        } else if (preProcess != null) return preProcess.preProcess(tok.getPartOfSpeech().startsWith("verbe") ? tok.getBaseForm() : tok.getSurfaceForm());
        else return tok.getSurfaceForm();
    }

    @Override
    public void setTokenPreProcessor(TokenPreProcess preProcess) {
        this.preProcess = preProcess;
    }
    
}

KuromojiIpadicTokenizerFactory.java


/**
 *Enveloppez l'usine de Kuromoji
 * @author 
 */
public class KuromojiIpadicTokenizerFactory implements TokenizerFactory {

    private TokenPreProcess preProcess;

    private static String preValue = "";
    
    @Override
    public Tokenizer create(String toTokenize) {
//        System.out.println(toTokenize);
        if (toTokenize == null || toTokenize.isEmpty()) {
            //Évitez l'analyse avec des espaces de demi-largeur, pas d'exceptions
            //Sinon, vous ne pourrez pas apprendre des documents avec des sauts de ligne consécutifs
            toTokenize = " ";
        }
        KuromojiIpadicTokenizer ret = new KuromojiIpadicTokenizer(toTokenize);
        ret.setTokenPreProcessor(preProcess);
        return ret;
    }

    @Override
    public Tokenizer create(InputStream paramInputStream) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void setTokenPreProcessor(TokenPreProcess preProcess) {
        this.preProcess = preProcess;
    }

    @Override
    public TokenPreProcess getTokenPreProcessor() {
        return this.preProcess;
    }
    
}

Laissez-les apprendre et produire les résultats

Utilisez ce gars.

WordVecSample.java


/**
 *Extraire des mots de phrases
 *La pertinence (les mots qui apparaissent fréquemment dans des positions proches sont des théories très pertinentes, même si elles sont bâclées)
 *Échantillon pour apprendre et calculer des mots très pertinents
 * @author 
 */
public class WordVecSample {
    public static void main(String[] args) throws IOException{

        /**
         *À l'origine pour l'anglais
         *Japanese Analyzer est utilisé pour les mots vides (mots qui ne sont pas évalués)
         *Bien que la cible de l'évaluation se limite aux verbes (forme de base) et à la nomenclature, il est difficile de cibler «aru», «iru», etc.
         */
        List<String> stopWords = new ArrayList<>();
        stopWords.addAll(Arrays.asList(JapaneseAnalyzer.getDefaultStopSet().toString().split(", ")));
        //Cette fois, j'ai également ajouté des chiffres chinois à titre d'essai
        stopWords.addAll(Arrays.asList("un","ré","Trois","quatre","Cinq","Six","Sept","Huit","Neuf","Dix"));
        
        /**
         *Corpus(Collection de phrases)Chargement des données
         *■ Étant donné que les données de formation sont extrêmement faibles cette fois, il est impossible de les mettre en pratique à ce niveau.
         *Au dernier échantillon ...
         */
        System.out.println( "Lecture des données d'entraînement..." );
        File f = new File( "D:\\deepleaning\\deepImpact.txt" );
        SentenceIterator ite = new LineSentenceIterator( f );
        //Hériter du préprocesseur et lisser le mot
        //À ce stade, il peut être préférable d'inclure la conversion kana demi-largeur
        ite.setPreProcessor((String sentence) -> sentence.toLowerCase().replaceAll("\n", " "));
        
        /**
         *Décomposer les phrases en mots
         *Le but est de lisser la notation avant la division des jetons dans le pré-processus
         *■ Pour l'analyse morphologique, remplacez-le de sorte que kuromoji soit utilisé car il prend en charge le japonais.
         */
        final EndingPreProcessor preProcessor = new EndingPreProcessor();
        KuromojiIpadicTokenizerFactory tokenizer = new KuromojiIpadicTokenizerFactory();
        tokenizer.setTokenPreProcessor((String token) -> {
            if(token == null) {
                return " ";
            } else {
                token = token.toLowerCase();
                String base = preProcessor.preProcess( token );
                return base;
            }
        });

        /**
         *Création d'un modèle (tokenizer et divers paramètres)
         *Cette fois, j'ai ajusté les paramètres pour pouvoir obtenir un résultat comme celui-là en quelques phrases.
         */
        System.out.println( "Construire un modèle..." );
        Word2Vec vec = new Word2Vec.Builder()
            .minWordFrequency( 1 )          //N'apprenez pas les mots avec moins que le nombre d'apparitions spécifié ⇒ Cette fois, il y a peu de corsus, donc le réglage est bas
            .iterations( 3 )                //Nombre d'itérations pendant l'apprentissage
            .batchSize( 1000 )              //Nombre maximum de mots à apprendre en une itération
            .layerSize( 120 )               //Nombre de dimensions vectorielles des mots
            .learningRate( 0.09 )           //Taux d'apprentissage
            .minLearningRate( 1e-3 )        //Taux d'apprentissage minimum
            .useAdaGrad( false )            // http://www.jmlr.org/papers/volume12/duchi11a/duchi11a.pdf non utilisé
            .negativeSample( 30 )           //Nombre de réponses inversées utilisées dans Skipgram Si vous avez beaucoup de corsus, vous devriez probablement le réduire.
            .stopWords(stopWords)           //Mots exclus: excluez les mots qui apparaissent partout, comme être présent
            .iterate( ite )                 //Modèle Corsus
            .tokenizerFactory(tokenizer)    //Tokenizer
            .build();

        /**
         *Apprentissage
         */
        System.out.println( "Apprentissage..." );
        vec.fit();

        /**
         *Modèle de résultat d'entraînement en sortie pour analyse
         *En fait, c'est une bonne idée de persister cela par des moyens appropriés.
         */
        WordVectorSerializer.writeWordVectors( vec , "D:\\words2.txt" );

        /**
         *Sortie des résultats d'apprentissage
         */
        /*
            //La similitude entre deux mots peut être calculée par la distance cosinus, mais comme il y a peu d'échantillons, seuls les commentaires sont écrits.
            String word1 = "Mot 1";
            String word2 = "Mot 2";
            double similarity = vec.similarity( word1 , word2 );
            System.out.println( String.format( "The similarity between 「%s」 and 「%s」 is %f" , word1 , word2 , similarity ) );
        */

        //Essayez de sélectionner 5 mots similaires à n'importe quel mot
        String word = "impact profond";
        int ranking = 5;
        Collection<String> similarWords = vec.wordsNearest( word , ranking );
        System.out.println( String.format( "「%Mots qui sont présumés être étroitement liés à "s" ⇒%s" , word , similarWords ) );
    }
    
}

Résultat de sortie

À partir de la deuxième fois, les résultats d'apprentissage précédents ne seront pas hérités. Résultat de l'apprentissage réinitialisé à chaque fois

1ère fois


Mots qui sont présumés être étroitement liés à un "impact profond"
⇒ [Ligne droite,Cavalier,Baba,Courir,Symbolil Dorf]

Deuxième fois


Mots qui sont présumés être étroitement liés à un "impact profond"
⇒ [Taureau,André,Écrivain,gagner,Souligné]

3e fois


Mots qui sont présumés être étroitement liés à un "impact profond"
⇒ [recevoir,Billet de paris,Pour,grossissement,Cheval]

4ème fois


Mots qui sont présumés être étroitement liés à un "impact profond"
⇒ [Rencontre,Texte occidental,Évaluation,Hong Kong,Soi]

5ème fois


Mots qui sont présumés être étroitement liés à un "impact profond"
⇒ [Grades,le fer,courir,sirocco,viens]

La première fois, c'est comme ça. Cependant, la deuxième fois et les suivantes sont terribles. .. ..

Ce résultat ne peut pas être aidé car il s'agit d'une étude avec un seul article. Je pense que ce serait bien d'augmenter les données d'entraînement et d'ajuster les paramètres.

Cependant, un dictionnaire des noms de chevaux de course est ajouté pour empêcher la division des mots des noms de chevaux. Il semble quand même nécessaire d'ajouter quelques mots vides supplémentaires. Je me demande si je n'avais pas besoin d'un verbe.

Recommended Posts

Apprenez des documents d'apprentissage automatique (DeepLeaning4j) en Java et essayez d'extraire des mots fortement liés à un mot spécifique
Comment tester une méthode privée et la simuler partiellement en Java
Java crée un tableau dans un document Word
Essayez de créer un babillard en Java
[Introduction à l'informatique n ° 0: Essayez l'apprentissage automatique] Implémentons la méthode de calcul de la moyenne k en Java
Comment convertir A en A et A en A en utilisant le produit logique et la somme en Java
Essayez de résoudre un problème FizzBuzz restreint en Java
[Exemple d'amélioration de Java] Expérience d'apprentissage de Java en 2 mois et de changement de poste en programmeur
Comment développer et enregistrer une application Sota en Java