예제 #1
0
def test_unique_forms():
    categories = [common.LEMMA_KEY] + [",".join(x) for x in common.get_categories_marks("RU")]
    descr = (
        "ребёночек#ребёночек#детки#ребёночка#деток#ребёночку#деткам#ребёночка#деток#ребёночком#детками#ребёночке#детках"
    )
    paradigmer = Paradigm(categories, descr)
    paradigmer.make_unique_forms("ребёночек", return_principal=False)
예제 #2
0
def read_input(infile, language, method='first'):
    """
    Аргументы:
    ----------
    infile: файл с записями вида
    1 <лемма_1>
    <форма_11>,<лемма_1>,<морфологические_показатели_1>
    <форма_12>,<лемма_1>,<морфологические_показатели_2>
    ...
    2 <лемма_2>
    <форма_21>,<лемма_2>,<морфологические_показатели_1>
    <форма_22>,<лемма_2>,<морфологические_показатели_2>
    ...
    method: str, 'first' or 'all' (default='first')
    метод добавления форм в парадигму
    first --- добавляется только первая словоформа для данной граммемы
    all --- добавляются все словоформы

    Возвращает:
    ----------
    tables: список вида [(лемма_1, формы_1), (лемма_2, формы_2), ...]
    """
    # сразу создаём функцию, которая проверяет, следует ли добавлять форму
    # в список. Так делаем, чтобы if вызывался только 1 раз
    marks = get_categories_marks(language)
    if method == 'first':
        add_checker = (lambda x: (x is not None) and len(x) == 0)

        def table_adder(lemma, table_dict):
            # вычисляем формы для леммы
            table_dict[LEMMA_KEY] = [lemma]
            forms = [(elem[0] if len(elem) > 0 else '-')
                     for elem in table_dict.values()]
            # возвращает список, потому что в случае 'all'
            # придётся возвращать несколько парадигм, то есть список
            return [(lemma, forms)]
    elif method == 'all':
        add_checker = (lambda x: x is not None)

        def table_adder(lemma, table_dict):
            # вычисляем формы для леммы
            table_dict[LEMMA_KEY] = [lemma]
            form_variants_list = list(table_dict.values())
            for i, form_variants in enumerate(form_variants_list):
                if len(form_variants) == 0:
                    form_variants_list[i] = ['-']
            # либо для каждой формы одинаковое число вариантов,
            # либо для некоторых 1, а для других одно и то же k>1
            form_variants_counts = set(len(x) for x in form_variants_list)
            if len(form_variants_counts) == 2:
                min_count, max_count = sorted(form_variants_counts)
                if min_count == 1:
                    for i, form_variants in enumerate(form_variants_list):
                        if len(form_variants) == 1:
                            form_variants_list[i] *= max_count
                else:
                    form_variants_list = [[elem[0]]
                                          for elem in form_variants_list]
            elif len(form_variants_counts) >= 2:
                form_variants_list = [[elem[0]] for elem in form_variants_list]
            return [(lemma, list(elem)) for elem in zip(*form_variants_list)]
    else:
        sys.exit("Method must be 'first' or 'all'.")
    tables = []
    table_keys = [LEMMA_KEY] + marks
    current_table_dict = OrderedDict((mark, []) for mark in table_keys)
    has_forms = False  # индикатор того, нашлись ли у слова словоформы
    with open(infile, 'r', encoding='utf-8') as fin:
        for line in fin:
            line = line.strip()
            line = line.strip('\ufeff')  # удалим метку кодировки
            splitted_line = line.split(',')
            if len(splitted_line) == 1:
                # строчка вида i_1 <лемма_1>
                if has_forms:
                    tables += table_adder(lemma, current_table_dict)
                    current_table_dict = OrderedDict(
                        (mark, []) for mark in table_keys)
                    has_forms = False
                splitted_line = splitted_line[0].split("\t")
                # lemma = splitted_line[-1]
                index, lemma = splitted_line
                if int(index) % 500 == 1:
                    print(index)
            else:
                form, form_lemma = splitted_line[:2]
                if language != 'RU_verbs':
                    mark = tuple(splitted_line[2:])
                else:
                    mark = ",".join(splitted_line[2:])
                if form not in ['—', '-', ''] and form_lemma == lemma:
                    if add_checker(current_table_dict.get(mark, None)):
                        current_table_dict[mark].append(form)
                        has_forms = True
        if has_forms:
            tables += table_adder(lemma, current_table_dict)
    return tables
def cv_mode(testing_mode, language_code, multiclass, predict_lemmas,
            paradigm_file, counts_file, infile,
            train_fraction, feature_fraction, paradigm_counts_threshold,
            nfolds, selection_method, binarization_method, max_feature_length,
            output_train_dir=None, output_pred_dir=None):
    lemma_descriptions_list = process_lemmas_file(infile)
    data, labels_with_vars = read_lemmas(lemma_descriptions_list, multiclass=multiclass, return_joint=True)
    paradigm_descriptions_list = process_codes_file(paradigm_file)
    paradigm_table, paradigm_counts = read_paradigms(paradigm_descriptions_list)
    word_counts_table = read_counts(counts_file)
    if predict_lemmas:
        paradigm_handlers = {code: ParadigmSubstitutor(descr)
                             for descr, code in paradigm_table.items()}
    else:
        test_lemmas, pred_lemmas = None, None
    # подготовка для кросс-валидации
    classes = sorted(set(chain(*((x[0] for x in elem) for elem in labels_with_vars))))
    active_paradigm_codes = [i for i, count in paradigm_counts.items()
                             if count >= paradigm_counts_threshold]
    # зачем нужны метки???
    marks = [LEMMA_KEY] + [",".join(x) for x in get_categories_marks(language_code)]
    paradigms_by_codes = {code: descr for descr, code in paradigm_table.items()}
    # подготовка данных для локальных трансформаций
    if selection_method is None:
        selection_method = 'ambiguity'
    if nfolds == 0:
        train_data_length = int(train_fraction * len(data))
        train_data, test_data = [data[:train_data_length]], [data[train_data_length:]]
        train_labels_with_vars, test_labels_with_vars =\
            [labels_with_vars[:train_data_length]], [labels_with_vars[train_data_length:]]
        nfolds = 1
    else:
        test_data, train_data = [None] * nfolds, [None] * nfolds
        test_labels_with_vars, train_labels_with_vars = [None] * nfolds, [None] * nfolds
        for fold in range(nfolds):
            train_data[fold], test_data[fold], train_labels_with_vars[fold], test_labels_with_vars[fold] =\
                skcv.train_test_split(data, labels_with_vars, test_size = 1.0 - train_fraction,
                                      random_state = 100 * fold + 13)
        if predict_lemmas:
            test_lemmas = [None] * nfolds
            for fold in range(nfolds):
                test_lemmas[fold] = make_lemmas(paradigm_handlers, test_labels_with_vars[fold])
    predictions = [None] * nfolds
    prediction_probs = [None] * nfolds
    classes_by_cls = [None] * nfolds
    if predict_lemmas:
        pred_lemmas = [None] * nfolds
    # задаём классификатор
    # cls = ParadigmCorporaClassifier(marks, paradigm_table, word_counts_table,
    #                                 multiclass=multiclass, selection_method=selection_method,
    #                                 binarization_method=binarization_method,
    #                                 inner_feature_fraction=feature_fraction,
    #                                 active_paradigm_codes=active_paradigm_codes,
    #                                 paradigm_counts=paradigm_counts , smallest_prob=0.01)
    cls = ParadigmCorporaClassifier(paradigm_table, word_counts_table,
                                    multiclass=multiclass, selection_method=selection_method,
                                    binarization_method=binarization_method,
                                    inner_feature_fraction=feature_fraction,
                                    active_paradigm_codes=active_paradigm_codes,
                                    paradigm_counts=paradigm_counts , smallest_prob=0.001)
    cls_params = {'max_length': max_feature_length}
    transformation_handler = TransformationsHandler(paradigm_table, paradigm_counts)
    transformation_classifier_params = {'select_features': 'ambiguity',
                                        'selection_params': {'nfeatures': 0.1, 'min_count': 2}}
    # statprof.start()
    cls = JointParadigmClassifier(cls, transformation_handler, cls_params,
                                  transformation_classifier_params)
    # cls = CombinedParadigmClassifier(cls, transformation_handler, cls_params,
    #                                  transformation_classifier_params)
    # сохраняем тестовые данные
    # if output_train_dir is not None:
    #     if not os.path.exists(output_train_dir):
    #         os.makedirs(output_train_dir)
    #     for i, (train_sample, train_labels_sample) in\
    #             enumerate(zip(train_data, train_labels_with_vars), 1):
    #         write_joint_data(os.path.join(output_train_dir, "{0}.data".format(i)),
    #                          train_sample, train_labels_sample)
    # применяем классификатор к данным
    for i, (train_sample, train_labels_sample, test_sample, test_labels_sample) in\
            enumerate(zip(train_data, train_labels_with_vars, test_data, test_labels_with_vars)):
        cls.fit(train_sample, train_labels_sample)
        classes_by_cls[i] = cls.classes_
        if testing_mode == 'predict':
            predictions[i] = cls.predict(test_sample)
        elif testing_mode == 'predict_proba':
            prediction_probs[i] = cls.predict_probs(test_sample)
            # в случае, если мы вернули вероятности,
            # то надо ещё извлечь классы
            if not multiclass:
                predictions[i] = [[elem[0][0]] for elem in prediction_probs[i]]
            else:
                raise NotImplementedError()
        if predict_lemmas:
            pred_lemmas[i] = make_lemmas(paradigm_handlers, predictions[i])
    # statprof.stop()
    # with open("statprof_{0:.1f}_{1:.1f}.stat".format(train_fraction,
    #                                                  feature_fraction), "w") as fout:
    #     with redirect_stdout(fout):
    #         statprof.display()
    if output_pred_dir:
        descrs_by_codes = {code: descr for descr, code in paradigm_table.items()}
        test_words = test_data
        if testing_mode == 'predict_proba':
            prediction_probs_for_output = prediction_probs
        else:
            prediction_probs_for_output = None
    else:
        descrs_by_codes, test_words, prediction_probs_for_output = None, None, None
    if not predict_lemmas:
        label_precisions, variable_precisions, form_precisions =\
            output_accuracies(classes, test_labels_with_vars, predictions, multiclass,
                              outfile=output_pred_dir, paradigm_descrs=descrs_by_codes,
                              test_words=test_words, predicted_probs=prediction_probs_for_output,
                              save_confusion_matrices=True)
        print("{0:<.2f}\t{1}\t{2:<.2f}\t{3:<.2f}\t{4:<.2f}".format(
            train_fraction, cls.paradigm_classifier.nfeatures,
            100 * np.mean(label_precisions), 100 * np.mean(variable_precisions),
            100 * np.mean(form_precisions)))
    else:
        label_precisions, variable_precisions, lemma_precisions, form_precisions =\
            output_accuracies(classes, test_labels_with_vars, predictions,
                              multiclass, test_lemmas, pred_lemmas,
                              outfile=output_pred_dir, paradigm_descrs=descrs_by_codes,
                              test_words=test_words, predicted_probs=prediction_probs_for_output,
                              save_confusion_matrices=True)
        print("{0:<.2f}\t{1}\t{2:<.2f}\t{3:<.2f}\t{4:<.2f}\t{5:<.2f}".format(
            train_fraction, cls.paradigm_classifier.nfeatures,
            100 * np.mean(label_precisions), 100 * np.mean(variable_precisions),
            100 * np.mean(lemma_precisions), 100 * np.mean(form_precisions)))

    # statprof.stop()
    # with open("statprof_{0:.1f}_{1:.1f}.stat".format(fraction, feature_fraction), "w") as fout:
    #     with redirect_stdout(fout):
    #         statprof.display()
    # вычисляем точность и обрабатываем результаты
    # for curr_test_values, curr_pred_values in zip(test_values_with_codes, pred_values_with_codes):
    #     for first, second in zip(curr_test_values, curr_pred_values):
    #         first_code, first_vars = first[0].split('_')[0], tuple(first[0].split('_')[1:])
    #         second_code, second_vars = second[0].split('_')[0], tuple(second[0].split('_')[1:])
    #         if first_code == second_code and first_vars != second_vars:
    #             print('{0}\t{1}'.format(first, second))
    # if not multiclass:
    #     confusion_matrices = [skm.confusion_matrix(first, second, labels=classes)
    #                           for first, second in zip(firsts, seconds)]
    # сохраняем результаты классификации
    # if output_pred_dir is not None:
    #     if not os.path.exists(output_pred_dir):
    #         os.makedirs(output_pred_dir)
    #     if testing_mode == 'predict':
    #         for i, (test_sample, pred_labels_sample, true_labels_sample) in\
    #                 enumerate(zip(test_data, predictions, test_labels), 1):
    #             write_data(os.path.join(output_pred_dir, "{0}.data".format(i)),
    #                        test_sample, pred_labels_sample, true_labels_sample)
    #     elif testing_mode == 'predict_proba':
    #         for i, (test_sample, pred_probs_sample, labels_sample, cls_classes) in\
    #                 enumerate(zip(test_data, prediction_probs, test_labels, classes_by_cls), 1):
    #             write_probs_data(os.path.join(output_pred_dir, "{0}.prob".format(i)),
    #                              test_sample, pred_probs_sample, cls_classes, labels_sample)
    # сохраняем матрицы ошибок классификации
    # if not multiclass and nfolds <= 1:
    #     confusion_matrices_folder = "confusion_matrices"
    #     if not os.path.exists(confusion_matrices_folder):
    #         os.makedirs(confusion_matrices_folder)
    #     dest = os.path.join(confusion_matrices_folder,
    #                         "confusion_matrix_{0}_{1:<.2f}_{2:<.2f}.out".format(
    #                             max_length, fraction, feature_fraction))
    #     with open(dest, "w", encoding="utf8") as fout:
    #         fout.write("{0:<4}".format("") +
    #                    "".join("{0:>4}".format(label) for label in classes) + "\n")
    #         for label, elem in zip(cls.classes_, confusion_matrices[0]):
    #             nonzero_positions = np.nonzero(elem)
    #             nonzero_counts = np.take(elem, nonzero_positions)[0]
    #             nonzero_labels = np.take(classes, nonzero_positions)[0]
    #             fout.write("{0:<4}\t".format(label))
    #             fout.write("\t".join("{0}:{1}".format(*pair)
    #                                  for pair in sorted(zip(nonzero_labels, nonzero_counts),
    #                                                     key=(lambda x: x[1]), reverse=True))
    #                        + "\n")
    return
예제 #4
0
def test_unique_forms():
    categories = [common.LEMMA_KEY
                  ] + [",".join(x) for x in common.get_categories_marks('RU')]
    descr = "ребёночек#ребёночек#детки#ребёночка#деток#ребёночку#деткам#ребёночка#деток#ребёночком#детками#ребёночке#детках"
    paradigmer = Paradigm(categories, descr)
    paradigmer.make_unique_forms("ребёночек", return_principal=False)
예제 #5
0
def read_input(infile, language, method='first'):
    """
    Аргументы:
    ----------
    infile: файл с записями вида
    1 <лемма_1>
    <форма_11>,<лемма_1>,<морфологические_показатели_1>
    <форма_12>,<лемма_1>,<морфологические_показатели_2>
    ...
    2 <лемма_2>
    <форма_21>,<лемма_2>,<морфологические_показатели_1>
    <форма_22>,<лемма_2>,<морфологические_показатели_2>
    ...
    method: str, 'first' or 'all' (default='first')
    метод добавления форм в парадигму
    first --- добавляется только первая словоформа для данной граммемы
    all --- добавляются все словоформы

    Возвращает:
    ----------
    tables: список вида [(лемма_1, формы_1), (лемма_2, формы_2), ...]
    """
    # сразу создаём функцию, которая проверяет, следует ли добавлять форму
    # в список. Так делаем, чтобы if вызывался только 1 раз
    marks = get_categories_marks(language)
    if method == 'first':
        add_checker = (lambda x: (x is not None) and len(x) == 0)
        def table_adder(lemma, table_dict):
            # вычисляем формы для леммы
            table_dict[LEMMA_KEY] = [lemma]
            forms = [(elem[0] if len(elem) > 0 else '-') for elem in table_dict.values()]
            # возвращает список, потому что в случае 'all'
            # придётся возвращать несколько парадигм, то есть список
            return [(lemma, forms)]
    elif method == 'all':
        add_checker = (lambda x: x is not None)
        def table_adder(lemma, table_dict):
            # вычисляем формы для леммы
            table_dict[LEMMA_KEY] = [lemma]
            form_variants_list = list(table_dict.values())
            for i, form_variants in enumerate(form_variants_list):
                if len(form_variants) == 0:
                    form_variants_list[i] = ['-']
            # либо для каждой формы одинаковое число вариантов,
            # либо для некоторых 1, а для других одно и то же k>1
            form_variants_counts = set(len(x) for x in form_variants_list)
            if len(form_variants_counts) == 2:
                min_count, max_count = sorted(form_variants_counts)
                if min_count == 1:
                    for i, form_variants in enumerate(form_variants_list):
                        if len(form_variants) == 1:
                            form_variants_list[i] *= max_count
                else:
                    form_variants_list = [[elem[0]] for elem in form_variants_list]
            elif len(form_variants_counts) >= 2:
                form_variants_list = [[elem[0]] for elem in form_variants_list]
            return [(lemma, list(elem)) for elem in zip(*form_variants_list)]
    else:
        sys.exit("Method must be 'first' or 'all'.")
    tables = []
    table_keys = [LEMMA_KEY] + marks
    current_table_dict = OrderedDict((mark, []) for mark in table_keys)
    has_forms = False  # индикатор того, нашлись ли у слова словоформы
    with open(infile, 'r', encoding='utf-8') as fin:
        for line in fin:
            line = line.strip()
            line = line.strip('\ufeff')  # удалим метку кодировки
            splitted_line = line.split(',')
            if len(splitted_line) == 1:
                # строчка вида i_1 <лемма_1>
                if has_forms:
                    tables += table_adder(lemma, current_table_dict)
                    current_table_dict = OrderedDict((mark, []) for mark in table_keys)
                    has_forms = False
                splitted_line = splitted_line[0].split("\t")
                # lemma = splitted_line[-1]
                index, lemma = splitted_line
                if int(index) % 500 == 1:
                    print(index)
            else:
                form, form_lemma = splitted_line[:2]
                if language != 'RU_verbs':
                    mark = tuple(splitted_line[2:])
                else:
                    mark = ",".join(splitted_line[2:])
                if form not in ['—', '-', ''] and form_lemma == lemma:
                    if add_checker(current_table_dict.get(mark, None)):
                        current_table_dict[mark].append(form)
                        has_forms = True
        if has_forms:
            tables += table_adder(lemma, current_table_dict)
    return tables