[PYTHON] Comment faites-vous "les trois premiers mots que vous avez trouvés"?

Avez-vous déjà vu cela sur Twitter ou Facebook? スナップショット17.jpeg C'est ce que j'ai inventé. Vous pouvez en trouver en cherchant.

** Comment faites-vous cela! ?? Je me demandais **, alors j'y ai réfléchi un instant. Tout le code est implémenté en Python3. Si vous utilisez 2.x et que vous utilisez souvent le japonais, changez. Si vous faites attention au code de caractère uniquement à l'entrée et à la sortie, vous n'avez pas à vous soucier de l'unicode ou du codec, c'est donc très facile.

Stratégie 1: Choisissez un hiragana complètement aléatoire

Stratégie 1


import random

h, w = 16, 16
USE_HIRAGANAS = ('Aiue Okakikuke Kosashi' +
        'Qu'est-ce que Nune no Hahifuhe Homami Mumemoya Yuyorari Rurewan' +
        'Gagiguge Gozajizuzezo Dajizu de Dobabibubebo Papipupepo')

for _ in range(h):
    print(''.join(random.choice(USE_HIRAGANAS) for _ in range(w)))

Résultats de la stratégie 1


Ruzuru Po Nuzu Jijiranuyo Audo Pepo
Geyojiname Hikepe no Patsume Abo
Zuko Pozazago Gibabora Hiwa Chiro Yubu
C'est incroyable.
Nemejikabare Newaboru Kisupibina
Noupi Homi ni Reze Unazamomu Obotsu
Robza Hopozae Shipsachi
Nato est Gozae Koto Dometsuse Pizozuso
Pas de bronzage et d'irrégularités
Ntepabesoyusupibi est un étranger
Meba et Hechinagake Yasuzumihoha
Yabudo Soewa ni Sajiya no Mobonunu
Mabiro Gozuru Yupiru Jiwazumosa
Regard et Sozuma Hoa Osaji Gezu Hameki
Chikoshige Bikinebo Pezazubo
J'ai peur d'avoir peur

Je n'ai pas envie de trouver un mot. Pardon.

Stratégie 2: Tenez compte de la fréquence d'apparition du hiragana et sélectionnez le hiragana couramment utilisé avec une forte probabilité.

Gcanna.ctd de cannadic Kai utilisé comme dictionnaire du système d'entrée japonais open source est utilisé comme exemple de chaîne de caractères hiragana. utilisé.

À propos, la fréquence d'apparition de chaque hiragana était comme ça. スナップショット19.jpeg (Reportez-vous à here pour savoir comment afficher le japonais dans matplotlib afin que cela ne devienne pas déroutant.)

Voici un exemple de code qui facilite le choix d'un hiragana avec une probabilité élevée.

Stratégie 2


def make_text1(hist, height, width):
    n = sum(hist.values())
    keyvalues = hist.most_common()
    a = [keyvalues[0][1]]
    for x in keyvalues[1:]:
        a.append(a[-1] + x[1])

    def _get():
        x = random.randrange(n)
        for i,y in enumerate(a):
            if x < y:
                return keyvalues[i][0]

    return '\n'.join([''.join([_get() for _ in range(width)])
                     for _ in range(height)])

D'ailleurs, hist suppose collections.Counter type. C'est une sous-classe de type dict et est similaire à defaultdict (lambda: 0) en termes de convivialité, C'est très pratique car vous pouvez additionner les types de compteurs et obtenir ((clé, valeur), ...) dans l'ordre décroissant avec Counter.most_common ().

Et en conséquence, une telle liste de hiragana a été obtenue.

Résultats de la stratégie 2


Kigorae Shiratsu Osen
Migodakote Azuchi Karigo no Ukuri
Bubuchi Dona Chinkefui Odakoshikofu
Yugitado Ganshin no Teumi Ii
Mesagen Aki de Biuro Hiroro
Peut-être que c'est léger et léger
Fuwanrosa Hiuta est Ujimi Kakubo
Chitsuke-n-mezan
Jiriyoji et Parugiko
Ne t'inquiète pas pour ça
Toseda Sarago est Sadamu Umomusin
Fuzoki Sezori Kuki Sachi Aiku Kafu
Riuuchi no Sato Toshito Mawachi
Chiira Utafuse Suma Biseki
Sohachi grinçant et grinçant
Nana Bakon Uta Hogiki Kuukoan

Il s'est considérablement amélioré. C'est plutôt bon. Cela vous donnera l'énergie de le chercher. Mais ne serait-ce pas un peu mieux?

Stratégie 3: Tenir compte de la probabilité de transition d'un hiragana à un autre

Bref, c'est le processus Markov au premier étage. Voici un extrait du code. À propos, markov est collections.defaultdict (collections.Counter), et markov ['a'] ['i'] compte le nombre de "i" après "a". Je vais. À l'origine, chaque élément devait être divisé par sum (markov ['a']. Valeurs ()) pour que ce soit une probabilité, mais comme il a été ignoré, cette fonction est également utilisée.

Stratégie 3


def tee(func, arg):
    func(arg)
    return arg

def make_text2(markov, hist, height, width):
    '''Une liste de hiragana qui considère également le prochain hiragana.'''
    def _get(up, left):
        '''Considérez la transition du caractère supérieur et la transition du caractère gauche'''
        c = norm_markov[up] + norm_markov[left]
        x = random.random() * 2.0
        y = 0.0
        for k,v in c.most_common():
            y += v
            if x <= y:
                #print('_get:', up, left, '-->', k)
                return k

    #Compte tenu de la transition entre le caractère supérieur et le caractère gauche, la colonne avant la 0ème colonne et la ligne avant la 0ème ligne sont
    #Ce sera nécessaire, mais pour plus de commodité, nous utiliserons une ligne faite à partir de la fréquence d'apparition de hiragana.
    firstcol = make_text1(hist, 1, width)
    prevline = make_text1(hist, 1, width).strip()
    #print('firstcol', firstcol)
    #print('prevline', prevline)

    #Normaliser markov.
    #Pour que le poids de la transition du caractère supérieur et de la transition du caractère gauche soit identique.
    norm_markov = {}
    for k1,cnt in markov.items():
        c = Counter()
        n = sum(cnt.values())
        for k2,v in cnt.items():
            c[k2] = v / n
        norm_markov[k1] = c

    a = []
    for i in range(height):
        line = []
        functools.reduce(lambda x,j: tee(line.append, _get(prevline[j], x)),
                         range(width), firstcol[i])
        a.append(''.join(line))
        prevline = line
    return '\n'.join(a)

À propos, pour créer markov, vous pouvez utiliser un code comme celui-ci. (J'en ai omis beaucoup)

markov Faisons


from collections import deque
from collections import defaultdict
from collections import Counter

def shiftiter(iterable, n):
    '''Generator which yields iterable[0:n], iterable[1:n+1], ...

    Example: shiftiter(range(5), 3) yields (0, 1, 2), (1, 2, 3), (2, 3, 4)'''
    # I used deque, but I'm not sure it is fastest way:(
    it = iter(iterable)
    try:
        a = deque([next(it) for _ in range(n)])
        yield tuple(a)
    except StopIteration:
        pass
    for x in it:
        a.popleft()
        a.append(x)
        yield tuple(a)


USE_HIRAGANAS = ('Aiue Okakikuke Kosashi' +
            'Qu'est-ce que Nune no Hahifuhe Homami Mumemoya Yuyorari Rurewan' +
            'Gagiguge Gozajizuzezo Dajizu de Dobabibubebo Papipupepo')

markov = defaultdict(Counter)
with open(FILENAME, encoding=FILEENCODING) as f:
    for line in f:
        hiragana = line.split()[0]
        for x,y in shiftiter(hiragana, 2):
            if x in USE_HIRAGANAS and y in USE_HIRAGANAS:
                markov[x][y] += 1

En conséquence, cela ressemble à ceci.

Résultats de la stratégie 3


Kisetsu Gejinkatonta Saikigose
Petit Shizun Rakui Otsubishi Kimebui
Gashiani Kahoi Shinyo Sato
Je suis si gentil
Ruiga Hokkokine Ushin Quand Gouri
Kehowaun Negoru Egipai Toushi
Tu es un étranger
Qu'est-ce que Sankeda Ichichi?
Nigini Omotoyo Heuri Kochise
Nregoka Senka Funuya Shinkuso
Ken est Mumeki Menshiro Kashiri Dakii
Naki Funamisai peut être bon
Sushi râpé
Tokei Jio-san ou Sonkaki Ogoto
Ngayama Yoshigoki Hojimami Shizu
Bichikuji Kobarichi Ichizumu Konguka

Souhaitez-vous rechercher cela? C'est aléatoire, donc je dois le faire plusieurs fois et en choisir un bon, mais j'ai l'impression que ça ne sert à rien. Ce n'est pas mauvais.

Considérations futures pour ceux qui ne sont pas encore satisfaits

Processus de Markov au deuxième étage ou plus

Vous voudrez peut-être l'essayer.

Comment choisir les lettres

Actuellement, nous sommes en train d'accumuler la distribution de probabilité à partir de la plus grande, de la normaliser à 0 à 1 et de la sélectionner avec un nombre aléatoire de 0 à 1. (En fait, c'est un peu différent, mais c'est presque comme ça) Mais dois-je choisir un hiragana qui n'apparaît qu'avec 1% de chance? Ne devrait-il pas être ignoré? Et je pense. Cependant, lorsque je l'ai remodelé pour que seulement 80% environ puissent être sélectionnés, un grand nombre de hiragana fréquemment utilisés tels que "n" et "u" ont été sélectionnés. Il semble qu'un ajustement soit nécessaire même du côté à haute fréquence.

Le code est github

Pour ceux qui sont intéressés: Le code est posté sur github. https://github.com/gyu-don/jikken/tree/master/markov Je n'ai pas téléchargé gcanna.ctd car il était difficile d'afficher la licence (GPL), mais j'ai téléchargé la sortie des données agrégées, donc je peux l'exécuter sans elle. (Si quelqu'un veut utiliser ce code avec la GPL, vous pouvez l'utiliser)

Vous pouvez télécharger gcanna.ctd ici. https://osdn.jp/projects/alt-cannadic/releases/

Recommended Posts

Comment faites-vous "les trois premiers mots que vous avez trouvés"?
Combien connaissez-vous les bases de Python?
Comment collectez-vous les informations?
Comprenez-vous le problème de Monty Hall?
Fabriquez-vous quelque chose comme une fusée?
Comment utiliser MkDocs pour la première fois
Vous pouvez le faire en 3 minutes! Comment créer un code QR (GIF) fonctionnel!