Depuis presque trois ans maintenant, j'enregistre scrupuleusement tous mes revenus et dépenses en hledger . Pourquoi exactement lui? C'est arrivé historiquement. Avec le début de 2018, j'ai commencé à tout écrire sur Google et en avril je suis allé au Japon. J'étais assis dans un hôtel et j'essayais de comprendre comment calculer correctement les prix dans différentes devises, et j'ai décidé d'écrire quelque chose sur le Lisp. Et il a écrit . Et il l'a montré aux gens dans le chat par courrier électronique. A quoi j'ai reçu la réponse "mais il y en a déjà une toute prête" et un lien vers hledger. Ensuite, j'ai fait glisser toutes mes entrées de la plaque Google vers hledger.
Ce que j'aime dans cette façon de comptabiliser les dépenses, c'est la capacité de sortir et de réécrire l'histoire. J'ai donc décidé que les écouteurs achetés l'année dernière pour ma femme ne devaient pas être écrits comme une "technique", mais comme des "cadeaux" - pas de problème.
Et en étudiant à un moment donné un chèque du Platypus, j'ai pensé, combien dois-je dépenser en chocolat? Spoiler - beaucoup. Je suis entré dans l'historique des commandes, y ai trouvé d'anciens reçus, réécrit les entrées par catégorie. Il n'y avait que des «dépenses: nourriture», mais maintenant «dépenses: nourriture: fruits» et autres. Dans le même temps, des articles ménagers y ont également été trouvés.
La première fois que je faisais cette réécriture complètement à la main. Autrement dit, il est rentré du magasin, a regardé le chèque et a noté de nombreuses lignes. Ensuite, j'ai automatisé un peu - j'ai fait un modèle pour une plaque dans emacs, où les lignes contiennent des produits avec leurs catégories et leurs prix, et dans la dernière colonne, le filtre par catégorie donne immédiatement les montants.
Mais les réseaux de neurones et autres datasatanism.
Une idée m'est venue que le réseau de neurones est tout à fait capable de comprendre que "GL.VIL.Oranges SELECT.fas.1kg" est un tel fruit, contrairement à "BOTTOM.HL.aton PODMOSKOVNY 400g" (pain, mais pour cela j'ai dû copier c'est le nom sur google).
Le problème à résoudre est évidemment la classification. Les noms de lignes sont soumis à l'entrée, et une catégorie est attendue en sortie. Au départ, je mettrai ces catégories manuellement, puis ne modifierai que les prédictions. En conséquence, le programme doit d'abord analyser le texte du chèque, sélectionner les noms des produits et leurs prix à partir de là, prédire la catégorie pour chaque nom. Montrez-moi le prédit pour que je puisse le corriger. Lorsque tout est en ordre, formez un ensemble de lignes pour le responsable.
, . , .
def parse_utk(lines):
while lines:
if lines[0].startswith(' '):
break
lines.pop(0)
else:
return
lines.pop(0)
result = []
while lines:
data = lines[0:6]
name, price, lines = lines[0], lines[3], lines[6:]
if name.startswith(''):
break
assert price.startswith('= ')
result.append((name, Decimal(price[2:]))
return result
, . .
, . , character-level , flair. – . – . , , .
, . " ", . . . 23 21. – .
hledger.
$ hledger bal -b thisyear -% -S
100.0 % expenses:
20.6 % <unsorted>
15.3 %
7.9 %
7.1 %
6.9 %
6.3 %
5.2 %
4.8 %
4.0 %
3.8 %
2.7 %
2.7 %
2.0 %
2.0 %
1.7 %
1.6 %
1.3 %
1.2 %
0.9 %
0.9 %
0.5 %
0.4 %
0.2 %
, . . , ( ) .
. , . , ?
– , . rule-based . ( - ) , ? , .
– NER. flair, ( ? ). . , IOB- … , .
rule-based , . . , "" . , . , , , . -, rule-based .
, . , . , . flair SpaceTokenizer, , . " ". , .
- - : " , , , ". , "1 107 99" , 107 99 . , ( ). ? , , .
, . . – " ", " " " ". NER . " " "".
. , (, , NewlineTokenizer), . , ColumnCorpus . \r, , . vertical tab (\x0b), RS US.
- , . , O, . , , . , , , .
, 'entry' 'entry'. – . 'O', , 'O\n', .
, . – flair.
. – , "" . .
rule-based , "" . , , rule-based . , , , rule-based .
Un seul chèque suffit pour former les tagueurs. Certes, au début, je devais terminer le script pour éditer les résultats intermédiaires, puis les enregistrer également dans le bon format (j'ai réussi à oublier le séparateur de colonnes spécial et je n'ai pas compris pendant une heure pourquoi rien ne fonctionnait). Il ne reste plus qu'à visser la partition "réseau neuronal" à l'analyseur principal.
Puis peignez le code et publiez.
Sources PS