Wednesday, July 13, 2022

Insert data to a series while incrementing a datetime index in Pandas

По документу

 https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.loc.html

Свойство loc используется для доступа к группе строк и столбцов по меткам или логическому массиву. Можно написать короткии код, использующий df.loc[index , label]

(.env) boris@boris-All-Series:~/DATAFRAMES$ cat InsertRowFrame1.py

import pandas as pd

df = pd.DataFrame(columns=['Name', 'Age'])

df.loc['2021-05-01 18:47:05', 'Name'] = 'Rick'

df.loc['2021-05-01 18:47:05', 'Age'] = 31

df.loc['2021-05-02 18:47:05', 'Name'] = 'Vivian'

df.loc['2021-05-02 18:47:05', 'Age'] = 34

df.loc['2021-05-03 18:47:05', 'Name'] = 'Djon'

df.loc['2021-05-03 18:47:05', 'Age'] = 36

print("\n************** BEFORE ROW INSERT *****************\n")

print(df)

line = pd.to_datetime("2022-06-01 19:40:05", format="%Y-%m-%d %H:%M:%S")

new_row = pd.DataFrame([['Robert', 37]], columns=['Name', 'Age'], index=[line])

df = pd.concat([df, pd.DataFrame(new_row)], ignore_index=False)

print("\n************* AFTER ROW INSERT *******************\n")

print(df)

(.env) boris@boris-All-Series:~/DATAFRAMES$ python3 InsertRowFrame1.py


************** BEFORE ROW INSERT *****************

                       Name Age

2021-05-01 18:47:05    Rick  31

2021-05-02 18:47:05  Vivian  34

2021-05-03 18:47:05    Djon  36

************* AFTER ROW INSERT *******************

                       Name Age

2021-05-01 18:47:05    Rick  31

2021-05-02 18:47:05  Vivian  34

2021-05-03 18:47:05    Djon  36

2022-06-01 19:40:05  Robert  37































Monday, July 11, 2022

Develop Voting Ensembles With Python

 Классификатор голосования — это модель машинного обучения, которая обучается на ансамбле многочисленных моделей и прогнозирует результат (класс) на основе их наивысшей вероятности выбора класса в качестве результата.Он просто объединяет результаты каждого классификатора, переданного в классификатор голосования, и прогнозирует выходной класс на основе наибольшего большинства голосов. Идея состоит в том, чтобы вместо создания отдельных выделенных моделей и определения точности для каждой из них мы создали единую модель, которая обучается по этим моделям и прогнозирует результат на основе их совокупного большинства голосов для каждого класса вывода.

Классификатор голосования поддерживает два типа голосования.

Жесткое голосование: при жестком голосовании прогнозируемый выходной класс — это класс с наибольшим большинством голосов, то есть класс, который имел наибольшую вероятность быть предсказанным каждым из классификаторов. Предположим, что три классификатора предсказали выходной класс (A, A, B), поэтому здесь большинство предсказало A как выход. Следовательно, A будет окончательным прогнозом.

Мягкое голосование: при мягком голосовании выходной класс представляет собой прогноз, основанный на средней вероятности, данной этому классу. Предположим, что при вводе данных для трех моделей вероятность прогноза для класса A = (0,30, 0,47, 0,53) и B = (0,20, 0,32, 0,40). Таким образом, среднее значение для класса A составляет 0,4333, а для класса B — 0,3067. Очевидно, что победителем является класс A, поскольку он имеет самую высокую вероятность, усредненную по каждому классификатору.

====================

В общем случае присутсвия веса у каждого классификатора:

====================

Классификатор голосования можно рассматривать как более сильный метаклассификатор, который уравновешивает слабые стороны отдельных классификаторов в конкретном наборе данных.

Классификатор голосования — это групповой классификатор, который принимает входные данные в виде двух или более оценщиков и классифицирует данные на основе голосования большинства.

Классификатор жесткого голосования классифицирует данные на основе меток классов и весов, связанных с каждым классификатором.

Классификатор мягкого голосования классифицирует данные на основе вероятностей и весов, связанных с каждым классификатором.

=============================================

Ансамбль мягкого голосования для классификации

Мы можем продемонстрировать мягкое голосование с помощью алгоритма машины опорных векторов (SVM). Алгоритм SVM изначально не предсказывает вероятности, хотя его можно настроить для предсказания вероятностных оценок, установив для аргумента «вероятность» значение «Истина» в классе SVC. Мы можем подобрать пять различных версий алгоритма SVM с полиномиальным ядром, каждая из которых имеет разную полиномиальную степень, заданную с помощью аргумента «степень». Будем использовать степени 1-5. Мы ожидаем, что путем объединения предсказанных оценок вероятности членства в классе, предсказанных каждой отдельной моделью SVM, ансамбль мягкого голосования в среднем достигнет более высокой прогностической эффективности, чем любая автономная модель, используемая в ансамбле.

(.env) boris@boris-All-Series:~/VOTINGCLASS$ cat SoftVotingCLS.py

# compare soft voting ensemble to standalone classifiers

from numpy import mean

from numpy import std

from sklearn.datasets import make_classification

from sklearn.model_selection import cross_val_score

from sklearn.model_selection import RepeatedStratifiedKFold

from sklearn.svm import SVC

from sklearn.ensemble import VotingClassifier

from matplotlib import pyplot

 # get the dataset

def get_dataset():

X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=2)

return X, y

 # get a voting ensemble of models

def get_voting():

# define the base models

models = list()

models.append(('svm1', SVC(probability=True, kernel='poly', degree=1)))

models.append(('svm2', SVC(probability=True, kernel='poly', degree=2)))

models.append(('svm3', SVC(probability=True, kernel='poly', degree=3)))

models.append(('svm4', SVC(probability=True, kernel='poly', degree=4)))

models.append(('svm5', SVC(probability=True, kernel='poly', degree=5)))

# define the voting ensemble

ensemble = VotingClassifier(estimators=models, voting='soft')

return ensemble

 # get a list of models to evaluate

def get_models():

models = dict()

models['svm1'] = SVC(probability=True, kernel='poly', degree=1)

models['svm2'] = SVC(probability=True, kernel='poly', degree=2)

models['svm3'] = SVC(probability=True, kernel='poly', degree=3)

models['svm4'] = SVC(probability=True, kernel='poly', degree=4)

models['svm5'] = SVC(probability=True, kernel='poly', degree=5)

models['soft_voting'] = get_voting()

return models

 # evaluate a give model using cross-validation

def evaluate_model(model, X, y):

cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)

scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')

return scores

 # define dataset

X, y = get_dataset()

# get the models to evaluate

models = get_models()

# evaluate the models and store results

results, names = list(), list()

for name, model in models.items():

scores = evaluate_model(model, X, y)

results.append(scores)

names.append(name)

print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))

# plot model performance for comparison

pyplot.boxplot(results, labels=names, showmeans=True)

pyplot.show()

















Ансамбль жесткого голосования для классификации

Мы можем продемонстрировать жесткое голосование с помощью алгоритма k-ближайших соседей. Мы можем подобрать пять разных версий алгоритма KNN, каждая из которых имеет разное количество соседей, используемых при прогнозировании. Мы будем использовать 1, 3, 5, 7 и 9 соседей (нечетные числа, чтобы избежать ничьи). Мы ожидаем, что путем объединения предсказанных меток классов, предсказанных каждой отдельной моделью KNN, ансамбль жесткого голосования достигнет в среднем лучших прогнозирующих характеристик, чем любая автономная модель, используемая в ансамбле.

(.env) boris@boris-All-Series:~/VOTINGCLASS$ cat HardVotingCLS.py

# compare hard voting to standalone classifiers

from numpy import mean

from numpy import std

from sklearn.datasets import make_classification

from sklearn.model_selection import cross_val_score

from sklearn.model_selection import RepeatedStratifiedKFold

from sklearn.neighbors import KNeighborsClassifier

from sklearn.ensemble import VotingClassifier

from matplotlib import pyplot

 

# get the dataset

def get_dataset():

X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=2)

return X, y

 

# get a voting ensemble of models

def get_voting():

# define the base models

models = list()

models.append(('knn1', KNeighborsClassifier(n_neighbors=1)))

models.append(('knn3', KNeighborsClassifier(n_neighbors=3)))

models.append(('knn5', KNeighborsClassifier(n_neighbors=5)))

models.append(('knn7', KNeighborsClassifier(n_neighbors=7)))

models.append(('knn9', KNeighborsClassifier(n_neighbors=9)))

# define the voting ensemble

ensemble = VotingClassifier(estimators=models, voting='hard')

return ensemble

 

# get a list of models to evaluate

def get_models():

models = dict()

models['knn1'] = KNeighborsClassifier(n_neighbors=1)

models['knn3'] = KNeighborsClassifier(n_neighbors=3)

models['knn5'] = KNeighborsClassifier(n_neighbors=5)

models['knn7'] = KNeighborsClassifier(n_neighbors=7)

models['knn9'] = KNeighborsClassifier(n_neighbors=9)

models['hard_voting'] = get_voting()

return models

 

# evaluate a give model using cross-validation

def evaluate_model(model, X, y):

cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)

scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')

return scores

 

# define dataset

X, y = get_dataset()

# get the models to evaluate

models = get_models()

# evaluate the models and store results

results, names = list(), list()

for name, model in models.items():

scores = evaluate_model(model, X, y)

results.append(scores)

names.append(name)

print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))

# plot model performance for comparison

pyplot.boxplot(results, labels=names, showmeans=True)

pyplot.show()



























===============================

Plot the decision boundaries of a VotingClassifier

===============================

Сначала инициализируются три примерных классификатора (DecisionTreeClassifier, KNeighborsClassifier и SVC) и используются для инициализации мягкого голосования VotingClassifier с весами [2, 1, 2], что означает, что предсказанные вероятности DecisionTreeClassifier и SVC считаются в 2 раза больше, чем каждый. столько же, сколько веса классификатора KNeighborsClassifier при расчете усредненной вероятности.

(.env) boris@boris-All-Series:~/VOTINGCLASS$ cat plot_voting_decision_regions.py

from itertools import product

import matplotlib.pyplot as plt

from sklearn import datasets

from sklearn.tree import DecisionTreeClassifier

from sklearn.neighbors import KNeighborsClassifier

from sklearn.svm import SVC

from sklearn.ensemble import VotingClassifier

from sklearn.inspection import DecisionBoundaryDisplay

# Loading some example data

iris = datasets.load_iris()

X = iris.data[:, [0, 2]]

y = iris.target

# Training classifiers

clf1 = DecisionTreeClassifier(max_depth=4)

clf2 = KNeighborsClassifier(n_neighbors=7)

clf3 = SVC(gamma=0.1, kernel="rbf", probability=True)

eclf = VotingClassifier(

    estimators=[("dt", clf1), ("knn", clf2), ("svc", clf3)],

    voting="soft",

    weights=[2, 1, 2],

)

clf1.fit(X, y)

clf2.fit(X, y)

clf3.fit(X, y)

eclf.fit(X, y)

# Plotting decision regions

f, axarr = plt.subplots(2, 2, sharex="col", sharey="row", figsize=(10, 8))

for idx, clf, tt in zip(

    product([0, 1], [0, 1]),

    [clf1, clf2, clf3, eclf],

    ["Decision Tree (depth=4)", "KNN (k=7)", "Kernel SVM", "Soft Voting"],

):

    DecisionBoundaryDisplay.from_estimator(

        clf, X, alpha=0.4, ax=axarr[idx[0], idx[1]], response_method="predict"

    )

    axarr[idx[0], idx[1]].scatter(X[:, 0], X[:, 1], c=y, s=20, edgecolor="k")

    axarr[idx[0], idx[1]].set_title(tt)

plt.show()































Gradient Descent Equation in Logistic Regression

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

Определим модель логистической регрессии для задач бинарной классификации. Мы выбираем функцию гипотезы как сигмовидную функцию: 






Здесь theta обозначает вектор параметров. Для модели, содержащей n функций, мы имеем theta = [theta_0, theta_1, ..., theta_n], содержащую n + 1 параметр. Функция гипотезы аппроксимирует оценочную вероятность того, что фактический результат будет равен 1. Другими словами:







Более компактно это эквивалентно:





Функция стоимости резюмирует, насколько хорошо модель ведет себя. Другими словами, мы используем функцию стоимости, чтобы измерить, насколько прогнозы модели близки к фактическим результатам.В линейной регрессии мы используем среднеквадратичную ошибку (MSE) в качестве функции стоимости. Но в логистической регрессии использование среднего значения квадратов разностей между фактическими и прогнозируемыми результатами в качестве функции стоимости может дать волнообразное, невыпуклое решение; содержащий множество локальных оптимумов:









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

При решении задачи бинарной классификации логарифмическая стоимость ошибки зависит от значения y. Мы можем определить стоимость для двух случаев отдельно:





Что затем приводит к:







Потому что, когда фактический результат y = 1, стоимость равна 0 для h<theta> (x) = 1 и принимает максимальное значение для 

h<theta>(x) = 0. Точно так же, если y = 0, стоимость равно 0 для h<theta>(x) = 0.

Поскольку вывод может быть либо {0}, либо {1}, мы можем упростить уравнение:



Для m наблюдений мы можем рассчитать стоимость как:





Здесь «i» есть номер фактического класса . 

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





Предположим, у нас есть всего n функций. В этом случае у нас есть n параметров для вектора theta. Чтобы минимизировать нашу функцию стоимости, нам нужно запустить градиентный спуск для каждого параметра theta_j:






Кроме того, нам нужно обновлять каждый параметр одновременно для каждой итерации. Другими словами, нам нужно перебрать параметры theta_0,theta_1, …,theta_n в векторе theta = [theta_0,theta_1, ..., theta_n]. Чтобы завершить алгоритм, нам нужно значение частной производной по theta_j для J(theta), которое равно:







Включение этого в функцию градиентного спуска приводит к правилу обновления:





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



Friday, July 8, 2022

What is the purpose of binarization

 Бинаризация используется, когда вы хотите преобразовать вектор числовых признаков в логический вектор. В области обработки цифровых изображений бинаризация изображения — это процесс, посредством которого цветное изображение или изображение в градациях серого преобразуется в бинарное изображение, т. е. изображение только с двумя цветами (обычно черным и белым). Этот метод используется для распознавания объектов, форм и, в частности, символов. Благодаря бинаризации можно отличить интересующий объект от фона, на котором он находится. Функция preprocessing.Binarizer() выполняет бинарную обработку данных в соответствии с заданным порогом. Значения, превышающие пороговое значение, сопоставляются с 1, а значения, меньшие или равные пороговому значению, сопоставляются с 0. При пороговом значении по умолчанию, равном 0, только положительные значения сопоставляются с 1. В нашем случае установленное пороговое значение равно 1,4, поэтому значения, превышающие 1,4 сопоставляются с 1, а значения меньше 1,4 сопоставляются с 0.

==============================================

Фундаментальная идея этой техники заключается в проведении фиксированной демаркационной линии. Поэтому необходимо найти соответствующий порог и подтвердить, что все точки изображения, интенсивность света которых ниже определенного значения, принадлежат объекту (фону), а все точки с большей интенсивностью принадлежат фону (объекту). Бинаризация — это широко распространенная операция над данными подсчета, при которой аналитик может принять решение учитывать только наличие или отсутствие характеристики, а не количественное количество вхождений. В противном случае его можно использовать в качестве этапа предварительной обработки для оценок, учитывающих случайные булевы переменные.

(.env) [boris@ServerFedora35 BINARIZE]$ cat Binarize1.py

from sklearn import preprocessing

import numpy as np

data = np.array([[3, -1.5, 2, -5.4], [0, 4, -0.3, 2.1], [1, 3.3, -1.9, -4.3]])

print(data)

data_binarized = preprocessing.Binarizer(threshold=1.4).transform(data)

print("Done data_binarized","\n",data_binarized )

print("\n")

(.env) [boris@ServerFedora35 BINARIZE]$ python Binarize1.py

[[ 3.  -1.5  2.  -5.4]

 [ 0.   4.  -0.3  2.1]

 [ 1.   3.3 -1.9 -4.3]]

Done data_binarized 

 [[1. 0. 1. 0.]

 [0. 1. 0. 1.]

 [0. 1. 0. 0.]]
































Thursday, July 7, 2022

Break out of multiple loops in Python

(.env) boris@boris-All-Series:~/VOTING$ cat doubleBreak.py

def verifyPresence(extList, z):

    # Iterating through all

    # lists present in extList:

    for subLst in extList:

        # Iterating through all the elements

        # of each of the nested lists in extList:

        for j in subLst:

            # Checking if any element in the

            # nested list is equal to z:

            if j == z:

                print('Element found')

                break

            else:

                print(j)

        else:

            continue

        break

 

# Driver Code:

extList = [[4, 5, 6, 7], [8, 9, 10],[11, 12, 13 , 14, 15]]

z = 12

verifyPresence(extList, z)

(.env) boris@boris-All-Series:~/VOTING$ python3 doubleBreak.py

4

5

6

7

8

9

10

11

Element found



























Convertion Decision Trees into Desision lists of rules (Python)

 Деревья решений и списки решений — два популярных языка гипотез, которые имеют немало общего. Ключевое отличие состоит в том, что деревья решений можно рассматривать как неупорядоченные наборы правил, где каждый лист дерева соответствует одному правилу с частью условия, состоящей из соединения всех меток ребер на пути от корня к этому листу. Иерархическая структура дерева гарантирует, что правила в наборе не перекрываются, то есть каждый пример может быть покрыт только одним правилом. Это дополнительное ограничение упрощает классификацию (отсутствие конфликтов из-за нескольких правил), но может привести к более сложным правилам. Например, было показано, что списки решений (упорядоченные наборы правил) с не более чем k условиями на правило строго более выразительны, чем деревья решений глубины k.Более того, ограничение алгоритмов обучения дерева решений непересекающимися правилами накладывает сильные ограничения.

========================

Список решений (также называемый упорядоченным набором правил) представляет собой набор отдельных правил классификации, которые в совокупности образуют классификатор. В отличие от неупорядоченного набора правил, списки решений имеют неотъемлемый порядок, что делает классификацию довольно простой. Для классификации нового экземпляра правила проверяются по порядку, и прогнозируется класс первого правила, которое охватывает экземпляр. Если не срабатывает индуцированное правило, вызывается правило по умолчанию, которое обычно предсказывает класс большинства.


(.env) boris@boris-All-Series:~/DecisionTree$ cat ConvertionDTree.py

from matplotlib import pyplot as plt

from sklearn import datasets

from sklearn.tree import DecisionTreeClassifier 

from sklearn import tree

import numpy as np

# Prepare the data data

iris = datasets.load_iris()

X = iris.data

y = iris.target

# Fit the classifier with max_depth=3

clf = DecisionTreeClassifier(max_depth=3, random_state=1234)

model = clf.fit(X, y)

text_representation = tree.export_text(clf, feature_names=iris.feature_names)

print(text_representation)

print('Decision Tree has been built','\n')

from sklearn.tree import _tree

def get_rules(tree, feature_names, class_names):

    tree_ = tree.tree_

    feature_name = [

        feature_names[i] if i != _tree.TREE_UNDEFINED else "undefined!"

        for i in tree_.feature

    ]

    paths = []

    path = []

    def recurse(node, path, paths):

        if tree_.feature[node] != _tree.TREE_UNDEFINED:

            name = feature_name[node]

            threshold = tree_.threshold[node]

            p1, p2 = list(path), list(path)

            p1 += [f"({name} <= {np.round(threshold, 3)})"]

            recurse(tree_.children_left[node], p1, paths)

            p2 += [f"({name} > {np.round(threshold, 3)})"]

            recurse(tree_.children_right[node], p2, paths)

        else:

            path += [(tree_.value[node], tree_.n_node_samples[node])]

            paths += [path]

    recurse(0, path, paths)

    # sort by samples count

    samples_count = [p[-1][1] for p in paths]

    ii = list(np.argsort(samples_count))

    paths = [paths[i] for i in reversed(ii)]

    rules = []

    for path in paths:

        rule = "if "

        for p in path[:-1]:

            if rule != "if ":

                rule += " and "

            rule += str(p)

        rule += " then "

        if class_names is None:

            rule += "response: "+str(np.round(path[-1][0][0][0],3))

        else:

            classes = path[-1][0][0]

            l = np.argmax(classes)

            rule += f"class: {class_names[l]} (proba: {np.round(100.0*classes[l]/np.sum(classes),2)}%)"

        rule += f" | based on {path[-1][1]:,} samples"

        rules += [rule]

    return rules

rules = get_rules(clf, iris.feature_names, iris.target_names)

for r in rules:

    print(r)


(.env) boris@boris-All-Series:~/DecisionTree$ python3 ConvertionDTree.py

|--- petal length (cm) <= 2.45

|   |--- class: 0

|--- petal length (cm) >  2.45

|   |--- petal width (cm) <= 1.75

|   |   |--- petal length (cm) <= 4.95

|   |   |   |--- class: 1

|   |   |--- petal length (cm) >  4.95

|   |   |   |--- class: 2

|   |--- petal width (cm) >  1.75

|   |   |--- petal length (cm) <= 4.85

|   |   |   |--- class: 2

|   |   |--- petal length (cm) >  4.85

|   |   |   |--- class: 2

Decision Tree has been built

if (petal length (cm) <= 2.45) then class: setosa (proba: 100.0%) | based on 50 samples

if (petal length (cm) > 2.45) and (petal width (cm) <= 1.75) and (petal length (cm) <= 4.95) then class: versicolor (proba: 97.92%) | based on 48 samples

if (petal length (cm) > 2.45) and (petal width (cm) > 1.75) and (petal length (cm) > 4.85) then class: virginica (proba: 100.0%) | based on 43 samples

if (petal length (cm) > 2.45) and (petal width (cm) <= 1.75) and (petal length (cm) > 4.95) then class: virginica (proba: 66.67%) | based on 6 samples

if (petal length (cm) > 2.45) and (petal width (cm) > 1.75) and (petal length (cm) <= 4.85) then class: virginica (proba: 66.67%) | based on 3 samples






























Heatmap example flights

 boris@boris-All-Series:~/SEABORN$ cat flightHeatMap.py

import pandas as pd

import numpy as np

import seaborn as sns

import matplotlib.pyplot as plt

sns.set()

flights = sns.load_dataset("flights")

flights = flights.pivot("month", "year", "passengers")

ax = sns.heatmap(flights)

plt.title("Heatmap Flight Data")

plt.show()