Pull to refresh

Comments 32

Вот у меня вопрос, я конечно все понимаю jdoc и все такое, но «Устанавливает параметр», «Констркутор по умолчанию», «Конструктор с параметрами», /* Константы */ и все такое это какая то жесть и мусор.
Согласен, изначально этот код демонстрировался в образовательных целях, забыл подчистить. Спасибо
Как способ получить список самых употребляемых слов это очень интересно, но не уверена в прикладном применении этого: мне кажется, знание местоимений и предлогов (а видимо они в топе этого 501 слова) недостаточно для понимания смысла.
Здесь вполне может сработать правило 80-20: чтобы понять 80% смысла, достаточно понять 20% слов, но ключевых, наименее употребляемых.
И еще интересно, как соотносится ваше понимание этих двух серий и процент слов которые вы знаете из «топа».
Я согласен, в топ безусловно попадёт много «мусора» и «шума». Второй стадией будет фильтрация этих результатов.
Что касается применения — методом анализа большого числа текстов (думаю что выберем определённую тематику) сформируются топ слов, отфильтруется от «мусора», разобьется по частям речи. Далее предполагается сделать интерфейс, который поможет запомнить эти слова.

Две серии просто для примера были взяты
UFO just landed and posted this here
Будем работать над этим, спасибо за идею
UFO just landed and posted this here
Увидеть код, который считает слова было не интересно, но он приведен. Посмотреть на список слов было интересно, но его в статье нет. Не вижу смысла ограничиваться двумя сериями. Анализировал аналогично двухлетнюю историю одного чата. Это около 200к слов на 11 человек. Интересно, что у каждого человека есть свои слова-фавориты.
Цель этого поста была описать принцип работы. Список слов по двум сериям Вы правы выкладывать нет смысла. Вот когда мы наберем статистику хотя бы по нескольким сезонам и разных сериалов, вот тогда список будет актуальный и обязательно будет представлен. Спасибо за идею про чаты.

Интересно было бы взять список слов, который рекомендуют учить, как раз для цели скорого участия в беседах и посмотреть какой % бесед в сериале можно понять используя этот список.


Список можно взять такой, например: http://fluent-forever.com/wp-content/uploads/2014/05/625-List-Alphabetical.pdf


Чисто же механические списки самых популярных слов издаются книгами для разных языков: поиск на amazon


Там печатают слова по частоте употребления в разных источниках: худ. книги, новости, интернет, разговоры.

Спасибо за идею, думаю реализуем такой эксперимент.

Простите, не смог удержаться :)


Код
from collections import Counter
import re

Q = 80

words = Counter(re.findall('[a-z\']+', open('subtitle.srt', encoding='windows-1252').read().lower()))
words_count = len(words)

popular = words.most_common(int(words_count*Q/100))
popular_count = len(popular)

print("Total:", words_count)
print("Popular ({}%):".format(Q), popular_count)
print("Top 10:")
for x in popular[:10]: print(x)
Вывод
Total: 905
Popular (80%): 724
Top 10:
('the', 165)
('you', 123)
('i', 107)
('it', 70)
('to', 60)
('a', 59)
('and', 52)
('of', 50)
('no', 42)
('is', 41)

По теме: если честно, ожидал увидеть в статье какой-то хардкорный NLP с применение интересных алгоритмов или библиотек. К сожалению, не увидел.

На данный момент всё существует на уровне — сделано первым способом как пришло в голову :-)
Согласен что это не самое лучшее решение, я и не претендую на пальму лидера. От части пост писался для получения конструктивной критики.
Кстати за пример спасибо.

Ну задача явно для скриптовых языков больше подходит. Повод изучить какой-нибудь Python

Думаю, дело не в скриптовом языке. Вот как оно могло бы на джаве выглядеть.
public class WordsCounter {

    private static final Comparator<Map.Entry<String, Long>> WORDS_COUNT_COMPARATOR =
            Comparator.<Map.Entry<String, Long>, Long>comparing(Map.Entry::getValue).reversed();

    public static void main(String[] args) {
        String text = "some text text some words many strong words and single bla bla";

        Map<String, Long> count = Arrays
                .stream(text.split("\\s+"))
                .map(WordsCounter::prepare)
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

        int wordsCount = count.size();

        System.out.println(wordsCount);

        count
                .entrySet()
                .stream()
                .sorted(WORDS_COUNT_COMPARATOR)
                .limit(wordsCount * 80 / 100)
                .forEach(System.out::println);
    }

    private static String prepare(String word) {
        return word; // // TODO: очистить от шлака и превести к нормальной форме
    }
}


На котлине это было бы еще в два раза короче.
Привести — кстати, о безграмотности.

Ммм… А можно


Comparator<Map.Entry<String, Long>> WORDS_COUNT_COMPARATOR = Map.Entry.comparingByValue(Comparator.reverseOrder());

В таком виде может и константа не нужна.

Да, писал наспех и не заметил. Спасибо.
Но ведь граматика… Вспомогательные слова могут ведь в корне изменить весь смысл. А еще формы глаголов, слово вроде одно, а смысл другой немножко. Думаю роботы для вас найдется.
Да мы над этим думаем, пока нет прямого ответа как оценивать грамматику и формы глаголов.

Скачал я как-то такой список самых частых слов, кажется отсюда. Оказалось, что топовую тысячу я знал тогда (~4-5 лет назад) почти полностью, за исключением 4 или 5 слов.


Проблемы в понимании всё равно были, особенно когда слушал разговор людей между собой, которые не старались упростить свою речь в угоду мне. Основная проблема для меня — именно различать слова во время быстрой речи, тем более с акцентом. Потому и фильмы смотреть могу, к сожалению, только с субтитрами. Вторая проблема — сленг.

Спрячьте код под кат, а то после прочтения можно получить легкий шок и забыть уже выученные английские слова.
Как я понял, автор еще не очень крепко освоился в джаве и это был своего рода проба пера. Вероятно проба стримов. Я позволю себе несколько замечаний по коду, которые возможно помогут задуматься о мелочах кода, из которых в итоге и состоит результат, который выдает разработчик.

1. Не стоит писать в интерфейсах public у методов, все методы интерфейса по-умолчанию public, все об этом знают, а модификаторы только загромождают код. И уж тем более не стоит писать abstract — в интерфейсе по определению все методы абстрактные (если не дефолтные :-)
2. Не надо создавать коммент (или блок комента вроде описания полей) если он не несет никакой информации, например — имя и тип и так видно в коде, а комментарии засоряют код как и любая другая информация.
3. Когда создаешь бины, лучше всего начать с неизменяемой версии (без setter-ов), изменять это только если есть действительная в том необходимость. Тоже самое с методами и конструкторами — не создавать их без необходимости. Ну и можно избавить читателей вашего кода от вызова Object.super() и определения serialVersionUID — это явно никак вам в данном случае не помогает.
4. private final — это не константы (см TextAnalyzerImp), а неизменяемые поля. Константы — private static final. И еще. ONE_WORD=1 это не просто бессмысленная константа, она еще и вредная, потому что она не только не упрощает понимание, но еще и заставляет пойти и посмотреть, какое же значение у неё, потому что не может быть, чтобы для инкремента на один была сделана отдельная константа.
5. TextAnalyzer конечно хороший интерфейс, но в вашей программе абсолютно бесполезный. Он даже тесты написать вам не поможет.
6. Совершенно непонятно, зачем в WordStats хранится ReceivedText — лучше избегать лишних зависимостей, а в данном случае бин статистики хранит в себе текст — это даже логически не очень понятно.
7. Раз уж мы говорим о java8
Map.Entry.comparingByValue(
				       (Integer value1, Integer value2) -> (
                                                 value1.equals(value2)) ? 0 : ((value1 < value2) ? 1 : -1)
                                       )
// если я правильно понял, это
Map.Entry.comparingByValue(Comparator.reverseOrder())

да и сразу за этим кодом от stream-ов мы переходим к iterator-у и сваливаемся в полный императив — выглядит странно. Суммирование, например, можно было бы написать так:
wordsMap.values().stream().mapToInt(Integer::intValue).sum()

8. Я и сам довольно безграмотный, но обычно пытаюсь проверить слово, если не уверен, как оно пишется: «процентрого соотнашения». Это кстати, заодно и подводит нас к мысли, что все, что мы пишем в коде не бесплатно, даже коменты, я уж не говорю обо всем остальном.
Раз уж начал, то вот еще:
1.
if (wordsMap.containsKey(newWord)) {
	wordsMap.replace(newWord, wordsMap.get(newWord) + ONE_WORD);
} else {
	wordsMap.put(newWord, ONE_WORD);
}
// можно так написать
wordsMap.put(newWord, wordsMap.computeIfAbsent(newWord, key -> 0) + 1);


2.
String newWord = "";
while (matcherWord.find()) {
	newWord = matcherWord.group("word");
// такая оптимизация не имеет смысла, только засоряет код, лучше объявить переменную по месту
while (matcherWord.find()) {
	String newWord = matcherWord.group("word");

3. «Поле receivedText — содержет ссылку на dto с текстом и процентом понимания.» Dto — это Data transfer object, в данном случае ничего никуда не transfer-ится, это просто бин.
UFO just landed and posted this here
Это действительно проба пера + получить критику.
Спасибо за конструктивные замечания.
Интерфейс TextAnalyzer я использовал, так как в дальнейшем этот код будет встраиваться в проект (Spring проект)
А по-моему, основной затык не в словах, а в их устойчивых сочетаниях — все эти «get down», «go over», «look for». Что толку знать значение отдельных кусочков, если в соединении они означают что-то не сводящееся к словосочетанию, полученному буквальным переводом. Ну и фразеологизмы всякие, переносные значения. В этих вот «самых популярных» словах множественность значений особенно чувствуется. В общем, проблема контекста во весь рост.

В итоге получается — все слова понял, а фразу целиком нет («угадал все буквы, но не смог назвать слово»).
В жизни то диалоги, думаю, сильно будут отличаться от сериальных.
Может быть стоит выдернуть слова из ютубовских роликов, где люди в компаниях разговаривают в естественной среде, а не на камеру.
Кстати, заодно, можно ещё расклассифицировать по типу обстановки, в которой происходят диалоги.
Было бы неплохо реализовать GUI с загрузкой TXT, PDF. Интересно бы проанализировать книги.
Согласен, мы думаем над этим :-)
Как-то смотрел ТВ передачу «Полиглот» и преподаватель-ведущий сказал запоминающуюся фразу о достаточности словаря в 300 слов для свободного общения. Фраза запомнилась и хотелось проверить на книгах.
Sign up to leave a comment.

Articles