[PYTHON] Journal de travail lors du grattage et de l'application de LDA

Aperçu

J'ai récupéré certaines URL dans Ruby et extrait des sujets à l'aide de LDA en Python.

  1. Grattage
  2. Analyse morphologique
  3. Dictionnaire original
  4. Mise en forme des données
  5. Exécution LDA

1. Grattage

Utilisation de Mechanize

gem install

$ bundle init
$ vim Gemfile
gem 'mechanize'
$ bundle install

Utilisation de mécaniser

Il est OK s'il fonctionne avec le fichier exemple suivant.

sample.rb


require 'mechanize'

agent = Mechanize.new
search_page = agent.get('URL appropriée')

search_page.search('body p').each do |y|
  p y.text
end

2. Analyse morphologique

Installez Mecab sur Mac

$ brew search mecab
mecab mecab-ipadic

$ brew install mecab mecab-ipadic
$ mecab

OK si mecab démarre

Utilisation de Natto

natto est un joyau qui enveloppe mecab installé sur votre système.

gem install

$ bundle init
$ vim Gemfile
gem 'natto'
$ bundle install

Spécification de MECAB_PATH

Pour utiliser natto, vous devez spécifier une variable d'environnement appelée MECAB_PATH.

$ find /usr/ -name "*mecab*" | grep dylib 
$ export MECAB_PATH=/usr//local/Cellar/mecab/0.996/lib/libmecab.dylib

http://yatta47.hateblo.jp/entry/2015/12/13/150525 https://github.com/buruzaemon/natto

Utilisation de mecab

Il est OK s'il fonctionne avec le fichier exemple suivant.

sample.rb


require 'natto'
text = 'Des cuisses et des cuisses'
nm = Natto::MeCab.new
nm.parse(text) do |n|
  puts "#{n.surface}\t#{n.feature}"
end

http://qiita.com/shizuma/items/d04facaa732f606f00ff http://d.hatena.ne.jp/otn/20090509

3. Dictionnaire original

Il devrait être fait à l'origine, mais omis cette fois.

Cette fois, au contraire, nous excluons la nomenclature, les synonymes généraux et la non-indépendance.

cond1 = features.include?('nom')
cond2 = features.include?('Général')
cond3 = !features.include?('Synonyme')
cond4 = !features.include?('Non indépendant')
if cond1 && cond2 && cond3 && cond4
  #Traitement requis
end

4. Code source du scraping au formatage des données

Objectif

Les données sont échangées entre python et ruby à l'aide de json. Plus précisément, préparez un csv qui résume l'URL de la page cible comme indiqué ci-dessous, et effectuez un scraping à partir de là pour le convertir en la structure de données requise pour LDA.

url
URL1
URL2
...
URLN

Enfin, le tableau suivant avec des mots arrangés pour chaque document est généré et sorti en json.

[
  ['human', 'interface', 'computer'],
  ['survey', 'user', 'computer', 'system', 'response', 'time'],
  ['eps', 'user', 'interface', 'system'],
  ['system', 'human', 'system', 'eps'],
  ['user', 'response', 'time'],
  ['trees'],
  ['graph', 'trees'],
  ['graph', 'minors', 'trees'],
  ['graph', 'minors', 'survey']
]

http://tohka383.hatenablog.jp/entry/20111205/1323071336 http://peaceandhilightandpython.hatenablog.com/entry/2013/12/06/082106

Code source réel

gem 'mechanize'
gem 'natto'
#Une classe qui génère un tableau d'URL à partir de csv
class UrlGetService
  require 'csv'

  def initialize(csv_path)
    @csv_path = csv_path
  end

  def web_urls
    @web_urls ||= -> do
      rows = []
      csv_file.each_with_index do |row, index|
        unless index == 0
          rows << row[0]
        end
      end
      rows
    end.call
  end

  private

    attr_reader :csv_path

    def csv_file
      @csv_file ||= -> do
        csv_text = File.read(csv_path)
        CSV.parse(csv_text)
      end.call
    end
end

#Une classe qui gratte une URL donnée
class WebScrapingService
  require 'mechanize'

  def initialize(url)
    @url = url
  end

  def texts
    @texts ||= -> do
      texts = ''
      page_contents.each do |content|
        texts += content.text
      end
      texts
    end.call
  end

  private

    attr_reader :url

    def page_contents
      @page_contents ||= scraping_agent.get(url).search('body p')
    end

    def scraping_agent
      @scraping_agent ||= Mechanize.new
    end
end

#Une classe qui analyse morphologiquement les résultats du grattage et crée un tableau de mots
class MorphologicalAnalysisService
  require 'natto'
  `export MECAB_PATH=/usr//local/Cellar/mecab/0.996/lib/libmecab.dylib`

  def initialize(texts)
    @texts = texts
  end

  def words
    words = []
    morphological_analysis_agent.parse(texts) do |word|
      features = word.feature.split(/,/)
      cond1 = features.include?('nom')
      cond2 = features.include?('Général')
      cond3 = !features.include?('Synonyme')
      cond4 = !features.include?('Non indépendant')
      if cond1 && cond2 && cond3 && cond4
        words << word.surface
      end
    end
    words
  end

  private

    attr_reader :texts

    def morphological_analysis_agent
      @morphological_analysis_agent ||= Natto::MeCab.new
    end
end

#Classe qui vide JSON en utilisant 3 classes
class DictionaryOutputService
  require 'json'

  def initialize(csv_path)
    @csv_path = csv_path
  end

  def output_json
    open('sample.json', 'w') do |f|
      JSON.dump(words_array, f)
    end
  end

  private

    attr_reader :csv_path

    def words_array
      @words_array ||= -> do
        web_urls.each_with_object([]) do |url, arr|
          texts = WebScrapingService.new(url).texts
          words = MorphologicalAnalysisService.new(texts).words
          white_lists =  words.inject(Hash.new(0)) { |h, a| h[a] += 1; h }.select { |_, c| c > 1 }.map { |w, _| w }
          arr << words.select { |w| white_lists.include?(w) }
        end
      end.call
    end

    def web_urls
      UrlGetService.new(csv_path).web_urls
    end
end

#Exécutez comme suit
csv_path = "YOUR_CSV_PATH/file_name.csv"
DictionaryOutputService.new(csv_path).output_json

5. Exécution LDA

Gestion des versions par pyenv

Au lieu d'utiliser le système python tel quel, utilisez le python installé et contrôlé par version.

git clone https://github.com/yyuu/pyenv.git ~/.pyenv

~/.bashrc


export PYENV_ROOT=$HOME/.pyenv
export PATH=$PYENV_ROOT/bin:$PATH
eval "$(pyenv init -)"

S'il s'agit de la série 3.5, vous ne pouvez pas tomber en installant des gensim.

sourve ~/.bashrc
pyenv install 3.5.0
pyenv shell 3.5.0

http://qiita.com/Kodaira_/items/feadfef9add468e3a85b

installation de gensim

Pour faire du LDA avec python, utilisez un module appelé gensim. outils de configuration requis pour l'installation du groupe électrogène

sudo easy_install -U setuptools

Installez gensim. Mettez également à jour les outils dépendants tels que numpy.

sudo -H pip install gensim -U

Code source

lda.py


from gensim import models, corpora

if __name__ == '__main__':
    #À l'origine, ce texte lit les fichiers JSON, etc.
    texts = [['human', 'interface', 'computer'],
             ['survey', 'user', 'computer', 'system', 'response', 'time'],
             ['eps', 'user', 'interface', 'system'],
             ['system', 'human', 'system', 'eps'],
             ['user', 'response', 'time'],
             ['trees'],
             ['graph', 'trees'],
             ['graph', 'minors', 'trees'],
             ['graph', 'minors', 'survey']]

    dictionary = corpora.Dictionary(texts)
    corpus = [dictionary.doc2bow(text) for text in texts]

    lda = models.ldamodel.LdaModel(corpus=corpus, num_topics=20, id2word=dictionary)

    # Topics
    for topic in lda.show_topics(-1):
        print('topic')
        print(topic)

    # Topic of each document
    for topics_per_document in lda[corpus]:
            print('topic of ecah document')
            print(topics_per_document)

https://radimrehurek.com/gensim/tut1.html#corpus-formats https://openbook4.me/projects/193/sections/1154 http://sucrose.hatenablog.com/entry/2013/10/29/001041

Référence: Exécuter LDA sur R

#Armée de paquet requise
install.packages("lda")
install.packages("ggplot2")
install.packages("reshape2")

#Données gratuites
data(cora.documents)
data(cora.vocab)

##Nombre de sujets
K <- 10

#Exécution de la fonction
result <- lda.collapsed.gibbs.sampler(cora.documents,
                                      K, #Nombre de sujets
                                      cora.vocab,
                                      25, #Nombre d'échantillons
                                      0.1, #Hyper paramètre α
                                      0.1, #Hyper paramètre β
                                      compute.log.likelihood=TRUE) 


#Top 5 des mots fréquents par sujet
top.words <- top.topic.words(result$topics, 5, by.score=TRUE)

Recommended Posts

Journal de travail lors du grattage et de l'application de LDA
Journal des travaux d'installation de Zsh et Prezto sur Mac
Lorsque send_keys ne fonctionne pas
Lorsque dropbox-sdk-python ne fonctionne pas