Tuesday, September 13, 2022

How to execute a program or call a system command from Python

 Модуль подпроцесса — это рекомендуемый Python способ выполнения команд оболочки.Это дает нам возможность подавлять вывод команд оболочки или связывать входные и выходные данные различных команд вместе, в то же время предоставляя аналогичный os.system()  опыт для основных случаев использования.

(.env) boris@boris-All-Series:~/BayesClassifier$ cat cmdRunPython1.py

import subprocess

list_files = subprocess.run(["ls", "-CRl"])

print("The exit code was: %d" % list_files.returncode)

(.env) boris@boris-All-Series:~/BayesClassifier$ python3 cmdRunPython1.py

.:

total 64

-rw-rw-r-- 1 boris boris   733 сен 13 14:04 argMaximum.py

-rw-rw-r-- 1 boris boris   118 сен 13 19:34 cmdRunPython1.py

-rw-rw-r-- 1 boris boris   116 сен 13 19:36 cmdRunPython2.py

-rw-rw-r-- 1 boris boris   115 сен 13 19:41 cmdRunPython3.py

-rw-rw-r-- 1 boris boris   176 сен 13 19:25 cmdRunPython.py

drwxrwxr-x 2 boris boris  4096 сен 13 19:35 COPIES

-rw-rw-r-- 1 boris boris  2874 сен 13 12:00 GaussProcessRegr.py

-rwxrwxr-x 1 boris boris 16520 сен 13 19:43 hello

-rw-rw-r-- 1 boris boris   111 сен 13 19:43 hello.cpp

-rw-rw-r-- 1 boris boris  6123 сен 13 15:46 OptimalBayes1.py

-rw-rw-r-- 1 boris boris  3026 сен 13 12:20 OptimalBayes.py

./COPIES:

total 32

-rw-rw-r-- 1 boris boris  733 сен 13 19:35 argMaximum.py

-rw-rw-r-- 1 boris boris  118 сен 13 19:35 cmdRunPython1.py

-rw-rw-r-- 1 boris boris  110 сен 13 19:35 cmdRunPython2.py

-rw-rw-r-- 1 boris boris  176 сен 13 19:35 cmdRunPython.py

-rw-rw-r-- 1 boris boris 2874 сен 13 19:35 GaussProcessRegr.py

-rw-rw-r-- 1 boris boris 6123 сен 13 19:35 OptimalBayes1.py

-rw-rw-r-- 1 boris boris 3026 сен 13 19:35 OptimalBayes.py

The exit code was: 0

В первой строке мы импортируем модуль подпроцесса, который является частью стандартной библиотеки Python. Затем мы используем функцию subprocess.run() для выполнения команды. Как и os.system(), команда subprocess.run() возвращает код завершения того, что было выполнено.В отличие от os.system(), обратите внимание, что subprocess.run() требует в качестве входных данных список строк, а не одну строку. Первым элементом списка является имя команды. Остальные элементы списка — это флаги и аргументы команды.

Несколько других примеров

(.env) boris@boris-All-Series:~/BayesClassifier$ cat cmdRunPython2.py

import subprocess

list_files = subprocess.run(["df","-Th"])

print("The exit code was: %d" % list_files.returncode)

(.env) boris@boris-All-Series:~/BayesClassifier$ python3 cmdRunPython2.py

Filesystem     Type   Size  Used Avail Use% Mounted on

tmpfs          tmpfs  3,2G  2,2M  3,2G   1% /run

/dev/sda5      ext4   183G  118G   56G  68% /

tmpfs          tmpfs   16G  297M   16G   2% /dev/shm

tmpfs          tmpfs  5,0M  4,0K  5,0M   1% /run/lock

/dev/sda3      ext4   1,4G  174M  1,1G  14% /boot

tmpfs          tmpfs   16G     0   16G   0% /run/qemu

tmpfs          tmpfs  3,2G  124K  3,2G   1% /run/user/1000

The exit code was: 0

(.env) boris@boris-All-Series:~/BayesClassifier$ cat hello.cpp

#include <iostream>

int main()

{

   std::cout << "Running binary code via Python" << std::endl;

   return 0;

}

(.env) boris@boris-All-Series:~/BayesClassifier$ g++ -o hello  hello.cpp

(.env) boris@boris-All-Series:~/BayesClassifier$ cat cmdRunPython3.py

import subprocess

list_files = subprocess.run(["./hello"])

print("The exit code was: %d" % list_files.returncode)

(.env) boris@boris-All-Series:~/BayesClassifier$ cat cmdRunPython3.py

import subprocess

list_files = subprocess.run(["./hello"])

print("The exit code was: %d" % list_files.returncode)

(.env) boris@boris-All-Series:~/BayesClassifier$ python3 cmdRunPython3.py

Running binary code via Python

The exit code was: 0






























Чтобы управлять вводом и выводом с помощью subprocess.Popen, нам нужно использовать метод Communicate(). В новый файл с именем cat_Popen.py добавьте следующий фрагмент кода:

(.env) boris@boris-All-Series:~/BayesClassifier$ cat cat_Popen.py

import subprocess
useless_cat_call = subprocess.Popen(["cat"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
output, errors = useless_cat_call.communicate(input="Hello from the other side!")
useless_cat_call.wait()
print(output)
print(errors)

(.env) boris@boris-All-Series:~/BayesClassifier$ python3 cat_Popen.py
Hello from the other side!


Bayes Optimal Classifier

 Теорема Байеса, которая обеспечивает систематические средства вычисления условной вероятности, используется для ее описания. Это также связано с апостериорным максимумом (MAP), вероятностной основой для определения наиболее вероятной гипотезы для набора обучающих данных. Возьмем пространство гипотез, в котором есть 3 гипотезы h1, h2 и h3.

Апостериорные вероятности гипотез таковы:

h1 -> 0,4

h2 -> 0,3

h3 -> 0,3

Следовательно, h1 является MAP-гипотезой. 

MAP => макс.  позднейший

Предположим, что встречается новый экземпляр x, который классифицируется как отрицательный по h2 и h3, но положительный по h1.Принимая во внимание все гипотезы, вероятность того, что x положительна, равна 0,4, а вероятность того, что она отрицательна, равна 0,6. Классификация, созданная гипотезой MAP, отличается от наиболее вероятной классификации в этом случае, которая является отрицательной. 

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

Наиболее вероятная классификация нового случая получается путем объединения предсказаний всех гипотез, взвешенных по их апостериорным вероятностям.

Уравнение ниже демонстрирует, как рассчитать условную вероятность для нового экземпляра (vj) с учетом обучающих данных (D) с учетом пространства гипотез (H).

Если вероятной классификацией нового примера может быть любое значение vj из множества V, вероятность P(vj/D) того, что правильной классификацией для нового примера является vj, равна просто

                   P(vj|D) = Sum{h ∈ H} P(vj|hj)*P(hj|D) 

 Bayes optimal classification is :

argmax         Sigma P(vj|hj)*P(hj|D)                 
                         vj  ∈ V          hj ∈ H

где V множестство экземпляров

Рассмотрим пример для оптимальной классификации Байеса,  пусть имеется 5 гипотез с h1 по h5.

      P(hi/D)       P(F/ hi)       P(L/hi)       P(R/hi)
        0.4                  1                  0                  0
        0.2                  0                  1                  0
        0.1                  0                  0                  1
        0.1                  0                  1                  0
        0.2                  0                  1                  0

Таким образом, теория MAP утверждает, что робот должен двигаться вперед (F). Посмотрим, что предлагает оптимальная процедура Байеса.   


     

Таким образом, оптимальная процедура Байеса рекомендует роботу повернуть налево.

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

Thursday, September 8, 2022

Breadth-first search

 Техника поиска в ширину (BFS) — это систематическая стратегия поиска, которая начинается с начального узла (начальное состояние), и от начального узла поисковые действия применяются вниз по древовидной структуре в порядке ширины.

Поисковое действие состоит из:

Выбор узла в качестве текущего узла

Проверка текущего узла на соответствие критериям целевого теста

Если целевое состояние не достигнуто, выберите следующий узел в порядке ширины

Поиск заканчивается либо тогда, когда все узлы были просмотрены, либо если цель найдена.

В примере с ключом от машины порядок поиска BFS соответствует последовательности узлов: 1, 2, 3, 4, 5… и т. д. в порядке ширины. Поиск BFS сначала пройдет по всем комнатам, затем по всем столам, затем по всем ящикам в этой последовательности.

               1.(  Дом  )

                /    |     \

               /     |      \

       2.(комната A)  3.(комната B)  4.(комната C)

             /   *car key

            /        | 

       5.(стол1)  6.(стол2)


Зачем нужен алгоритм поиска в ширину?

Есть несколько причин, по которым вам следует использовать алгоритм BFS для обхода структуры данных графа. Ниже приведены некоторые важные особенности, которые делают алгоритм BFS необходимым:

Алгоритм BFS имеет простую и надежную архитектуру.

Алгоритм BFS помогает оценивать узлы в графе и определяет кратчайший путь для обхода узлов.

Алгоритм BFS может пройти по графу за наименьшее возможное количество итераций.

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

По сравнению с другими алгоритмами результат алгоритма BFS имеет высокий уровень точности.

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

Продолжая пример с ключом от машины, список инициализируется следующим образом:

[ 1 (дом) ]

После того, как узел 1 не прошел целевой тест, он удаляется из списка, а узлы-преемники 2, 3, 4 добавляются к списку:

[2. (комната А), 3 (комната Б), 4 (комната С)]

Когда узел 2 проверен и удален, а узел 5 добавлен:

[3 (комната B), 4 (комната C), 5 (стол 1)]

Допустим , что, поиск завершается успешно, когда узел 3 идентифицируется как целевое состояние, т. е. ключ от машины находится в комнате B. 

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

BFS — алгоритм исчерпывающего поиска. Это просто реализовать. И его можно применить к любой задаче поиска. Сравнивая BFS с алгоритмом поиска в глубину, BFS не страдает от какой-либо потенциальной проблемы с бесконечным циклом, которая может привести к сбою компьютера, тогда как поиск в глубину идет вглубь. Одним из недостатков BFS является то, что это «слепой» поиск, когда пространство поиска велико, производительность поиска будет низкой по сравнению с другими эвристическими поисками.

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

Sample of Python code


    






boris@boris-All-Series:~/BFS$ cat searchBFS2.py

from queue import Queue

class Graph:

    # Constructor

   def __init__(self, num_of_nodes, directed=True):

        self.m_num_of_nodes = num_of_nodes

        self.m_nodes = range(self.m_num_of_nodes)

        # Directed or Undirected

        self.m_directed = directed

        # Graph representation - Adjacency list

        # We use a dictionary to implement an adjacency list

        self.m_adj_list = {node: set() for node in self.m_nodes}      

    # Add edge to the graph

   def add_edge(self, node1, node2, weight=1):

        self.m_adj_list[node1].add((node2, weight))


        if not self.m_directed:

            self.m_adj_list[node2].add((node1, weight))

    

    # Print the graph representation

   def print_adj_list(self):

      for key in self.m_adj_list.keys():

        print("node", key, ": ", self.m_adj_list[key])


   def bfs(self, start_node, target_node):

    # Set of visited nodes to prevent loops

    visited = set()

    queue = Queue()


    # Add the start_node to the queue and visited list

    queue.put(start_node)

    visited.add(start_node)

    

    # start_node has not parents

    parent = dict()

    parent[start_node] = None


    # Perform step 3

    path_found = False

    while not queue.empty():

        current_node = queue.get()

        if current_node == target_node:

            path_found = True

            break


        for (next_node, weight) in self.m_adj_list[current_node]:

            if next_node not in visited:

                queue.put(next_node)

                parent[next_node] = current_node

                visited.add(next_node)

                

    # Path reconstruction

    path = []

    if path_found:

        path.append(target_node)

        while parent[target_node] is not None:

            path.append(parent[target_node]) 

            target_node = parent[target_node]

        path.reverse()

    return path 

graph = Graph(6, directed=False)

graph.add_edge(0, 1)

graph.add_edge(0, 2)

graph.add_edge(0, 3)

graph.add_edge(0, 4)

graph.add_edge(1, 2)

graph.add_edge(2, 3)

graph.add_edge(2, 5)

graph.add_edge(3, 4)

graph.add_edge(3, 5)

graph.add_edge(4, 5)


graph.print_adj_list()


path = []

path = graph.bfs(0, 5)

print(path)


boris@boris-All-Series:~/BFS$ python3 searchBFS2.py

node 0 :  {(3, 1), (1, 1), (4, 1), (2, 1)}

node 1 :  {(0, 1), (2, 1)}

node 2 :  {(0, 1), (1, 1), (5, 1), (3, 1)}

node 3 :  {(0, 1), (5, 1), (4, 1), (2, 1)}

node 4 :  {(0, 1), (5, 1), (3, 1)}

node 5 :  {(3, 1), (4, 1), (2, 1)}

[0, 3, 5]


What behaves like alpha but reversed

 Вы можете рассчитать плотность точек, нормализовать ее и закодировать в альфа-канале карты цветов.


(.env) boris@boris-All-Series:~/ALPHA$ cat alphaViceVersa.py

import numpy as np

from scipy import stats

import matplotlib.pyplot as plt

from matplotlib.colors import LinearSegmentedColormap

# this is synthetic example

N = 25000       # a very very large number

x = np.random.normal(0, 1, N)

y = np.random.normal(0, 1, N)

fig, (ax,ax2) = plt.subplots(ncols=2, figsize=(8,5))

ax.scatter(x, y, marker='.', alpha=0.1)

values = np.vstack([x,y])

kernel = stats.gaussian_kde(values)

weights = kernel(values)

weights = weights/weights.max()

cols = plt.cm.Greys([0.8, 0.5])

cols[:,3] = [1., 0.005]

cmap = LinearSegmentedColormap.from_list("", cols)

ax2.scatter(x, y, c=weights, s = 1, marker='.', cmap=cmap)

plt.show()

(.env) boris@boris-All-Series:~/ALPHA$ python3 alphaViceVersa.py



























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

(.env) boris@boris-All-Series:~/ALPHA$ cat alphaViceVersa1.py
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

# this is synthetic example
N = 25000       # a very very large number
x = np.random.normal(0, 1, N)
y = np.random.normal(0, 1, N)

fig, ax = plt.subplots(figsize=(5,5))

values = np.vstack([x,y])
kernel = stats.gaussian_kde(values)
weights = kernel(values)
weights = weights/weights.max()
ax.scatter(x, y, c = weights, s=9, edgecolor="none", marker='.', cmap="magma")
plt.show()























Monday, September 5, 2022

Grouped Barplots in Python with Seaborn

 Barcharts: гистограммы хорошо использовать, когда у вас есть две переменные, одна из которых числовая, а другая может быть категориальной переменной. бар-плот может показать отношения между ними.

Сгруппированная гистограмма: Сгруппированная гистограмма полезна, когда у вас есть несколько категориальных переменных. Библиотека построения графиков Python Seaborn позволяет легко формировать сгруппированные гистограммы.

Groupby: функция Pandas dataframe.groupby() используется для разделения данных на группы на основе некоторых критериев. Объекты Pandas можно разделить по любой из их осей. Абстрактное определение группировки состоит в том, чтобы обеспечить сопоставление меток с именами групп.

(.env) boris@boris-All-Series:~/GROUPBY$ cat groupBySea.py

import seaborn as sb

import matplotlib.pyplot as plt

 # load dataset

df = sb.load_dataset('tips')

print(df)

print(df.info())

 # perform groupby

df = df.groupby(['size', 'day']).agg(mean_total_bill=("total_bill", 'mean'))

df = df.reset_index()

 # plot barplot

sb.barplot(x="size",

           y="mean_total_bill",

           hue="day",

           data=df)

plt.show()

















(.env) boris@boris-All-Series:~/GROUPBY$ cat groupBySea1.py

import seaborn as sb

import matplotlib.pyplot as plt

# load dataset

df = sb.load_dataset('anagrams')

print(df)

print(df.info())

# perform groupby

df = df.groupby(['num1', 'attnr']).agg(mean_num3=("num3", 'mean'))

df = df.reset_index()

# plot barplot

sb.barplot(x="num1",

           y="mean_num3",

           hue="attnr",

           data=df)

plt.show()






























Friday, September 2, 2022

Count same rows between multiple CSV files in Pandas

Задачу можно решить, используя 

pandas.merge(d1,d2,how = 'inner').  

Пример кода приведен ниже для двух датафреймов. В случае трех сделать :

inner_D1=pandas.merge(d1,d2,how = 'inner')

inner_D2=pandas.merge(d2,d3,how = 'inner')

и применить ту же схему к inner_D1 и inner_D2


 (.env) boris@boris-All-Series:~/GRADDECENTLGREG$ cat first.csv

X,Y

5923,1881

5322,1938

1453,2323

415,323232

7651,8901


(.env) boris@boris-All-Series:~/GRADDECENTLGREG$ cat second.csv

X,Y

3923,1881

5322,1938 

1453,2323

231,403

300,21213

312312,1312213

141516,412

7651,8901

 (.env) boris@boris-All-Series:~/GRADDECENTLGREG$ cat csvToDataframe.py

import pandas as pd

d1 = pd.read_csv('first.csv')

print(d1)

print('==================')

d2 = pd.read_csv('second.csv')

print(d2)

rows_in_common = 0

print('==================')

inner_DF = pd.merge(d1,d2,how = 'inner')

print(inner_DF)

rows_in_common = len(inner_DF)

print("=================")

print("rows_in_common = ",rows_in_common)

(.env) boris@boris-All-Series:~/GRADDECENTLGREG$ python3 csvToDataframe.py

      X       Y

0  5923    1881

1  5322    1938

2  1453    2323

3   415  323232

4  7651    8901

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

        X        Y

0    3923     1881

1    5322     1938

2    1453     2323

3     231      403

4     300    21213

5  312312  1312213

6  141516      412

7    7651     8901

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

      X     Y

0  5322  1938

1  1453  2323

2  7651  8901

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

rows_in_common =  3