Lógica fuzzy

Fabricio Lucas
#LocalizaLabs
Published in
7 min readMar 25, 2024

Em todas nossas atividades do dia a dia lidamos com informações quantitivas como a temperatura do local que se está, quantidade de frutas compradas, qual o nosso peso, quanto uma ação subiu ou caiu, etc. Mas nosso cérebro não percebe de forma quantitativa as informações que usamos para tomar decisões ou avaliar a situação de interesse naquele momento. Nosso cérebro avalia de forma qualitativa, como em uma situação que se avalia o preço de um imóvel que custa R$1.000.000, o nosso cérebro quase que instintivamente avalia categorizando esse valor na forma como muito barato, barato, razoável, caro ou muito caro, mas a percepção dessa categorização não é algo determinístico. Percebemos na maioria das vezes a categoriza a que um valor pertence com incerteza, tendo confiança parcial que ela pode pertencer a uma categoria ou a outra, por exemplo, acreditando que o preço do imóvel em questão seja razoável ou caro.

Mesmo com percepções ou informações incertas conseguimos tomar decisões e avaliar o cenário, mas como podemos fazer com que máquinas tomem decisões lidando com percepções incertas de forma mais familiarizada ao raciocínio realizado por nós, humanos?

Diante dessa pergunta, uma ideia passou a ser aplicada desde a década de 1960 e hoje é amplamente utilizada na engenharia e em machine learning: É a da lógica fuzzy. Com a lógica fuzzy podemos, por exemplo, trabalhar com duas avaliações no exemplo do imóvel (uma avaliação considerando o preço caro e outra avaliação considerando razoável) concordando parcialmente com cada uma das avaliações, assim como fazemos em situações de incerteza quando utilizamos definições como “mais ou menos”, “um pouco”, “depende”, etc.

A tomada de decisão na lógica fuzzy, também chamado de controle fuzzy ocorre nos seguintes passos:

· Fuzzificação

· Inferência fuzzy

· Desfuzzificação

Fuzzificação

A etapa de fuzzificação é a etapa que calculamos o pertencimento do valor da variável de entrada em cada um dos grupos categóricos pré-definidos, que representam a percepção da variável. Para mapear o valor da variável nos conjuntos categóricos é feito o uso de funções de pertinência. No exemplo dado anteriormente, os conjunto fuzzy são muito barato, barato, razoável etc, e as funções que representam esses conjuntos podem ter diferentes formas para cada conjunto fuzzy (função triangular, trapezoidal, gaussiana, etc) podendo ser obtidas através de análises de distribuição estatística da opinião de um grupo de pessoas a cerca do quanto acreditam que determinados valores pertencem a um conjunto fuzzy ou mesmo arbitrariamente e ajustada ao longo do tempo, mas devem respeitar algumas regras:

· Devem existir somente em um intervalo de valores entre 0 e 1

· A soma dos valores de pertinência de todos os conjuntos fuzzy de uma variável para cada valor não pode ser maior que 1

· Um valor deve pertencer obrigatoriamente a pelo menos um dos grupos

Vamos imaginar uma situação hipotética de controle de distância de um veículo em relação a outro trafegando por uma via como uma aplicação de controle fuzzy para tomada de decisão. As variáveis de entrada aqui serão a velocidade do veículo e a distância ao veículo à frente, e a pressão sobre os freios como a nossa variável de controle. Podemos representar os conjuntos fuzzy que representam as variáveis de entrada através do seguinte código:

import numpy as np
import skfuzzy as fuzz
from skfuzzy import control as ctrl
# Variáveis de entrada
# DEFINIÇÃO DAS FUNÇÕES DE PERTINÊNCIA
# velocidade
velocidade['baixa'] = fuzz.trimf(velocidade.universe, [0, 0, 30])
velocidade['media'] = fuzz.trimf(velocidade.universe, [0,30,100])
velocidade['alta'] = fuzz.trapmf(velocidade.universe, [30, 100,200,200])

# distancia
distancia['perto'] = fuzz.trimf(distancia.universe, [0, 0, 15])
distancia['mediana'] = fuzz.trapmf(distancia.universe, [0, 15, 50, 100])
distancia['longe'] = fuzz.trapmf(distancia.universe, [50, 100, 150, 150])
velocidade.view()

distancia.view()

Como podemos ver, temos diferentes conjuntos fuzzy que se sobrepõe sobre determinadas faixas e com formatos diferentes, e abrangem todo o espectro possível das variáveis de entrada.

Inferência fuzzy

Na sequência da lógia fuzzy, a próxima etapa é a inferência fuzzy, onde a partir dos valores fuzzy de cada variável analisada é feita a associação das regras do tipo SE-ENTÃO (também pré-definidas) para obter a tomada de decisão a cerca do cenário que se avalia, por exemplo, SE as nuvens no céu estão escuras ENTÃO devo levar guarda chuva. Também é possível relacionar duas ou mais variáveis em uma mesma regra, por exemplo, SE as nuvens do céu estão escuras E o vento sopra na direção contrária de onde estou ENTÃO não preciso levar guarda-chuva.

As regras fuzzy também são representadas por funções fuzzy onde o valor de pertinência nela depende da projeção dos valores fuzzy que geraram o acionamento da regra. O cálculo desse acionamento depende da operação fuzzy realizada. Existem diversas operações fuzzy, mas aqui vamos usar a operação Mamdani. Um operador de regras fuzzy é uma relação matemática para representar a implicação SE-ENTÃO. Essa implicação pode ocorrer de duas formas, usando a condição E ou usando a condição OU, onde a condição E é feita calculando o valor mínimo de pertinência entre conjuntos fuzzy de cada variável de entrada e a condição OU é feita calculando o valor máximo de pertinência.

Um exemplo pode ser visto a seguir onde a pressão sobre o freio (considerando como percentual de pressão possível no freio) é a variável a ser controlada e essa variável também deve ser fuzzificada para que possam ser aplicadas as regras definidas:

# Freio
Freio['leve'] = fuzz.trimf(Freio.universe, [0, 0, 33])
Freio['mediano'] = fuzz.trimf(Freio.universe, [0, 33,66])
Freio['forte'] = fuzz.trapmf(Freio.universe, [33, 66,90,np.inf])
Freio.view()

Algumas regras criadas podem ser definidas no seguinte código:

# regra 1 - se a velocidade é baixa e distância é média, então freio deve ser pressionado de forma leve
regra1 = ctrl.Rule(velocidade['baixa'] & distancia['mediana'], Freio['leve'])

# regra 2 - se a velocidade é mediana e distância é média, então freio deve ser pressionado de forma mediana
regra2 = ctrl.Rule(velocidade['media'] & distancia['mediana'], Freio['mediano'])

# regra 3 -se a velocidade é alta distância é longa, então freio deve ser pressionado de forma leve
regra3 = ctrl.Rule(velocidade['alta'] & distancia['longe'], Freio['leve'])

# regra 4 -se a velocidade é alta ou distância é perto, então freio deve ser pressionado de forma forte
regra4 = ctrl.Rule(velocidade['alta'] | distancia['perto'], Freio['forte'])

# regra 4 -se a velocidade é alta e distância é mediana, então freio deve ser pressionado de forma mediana
regra5 = ctrl.Rule(velocidade['alta'] & distancia['mediana'], Freio['mediano'])

imovel_ctrl = ctrl.ControlSystem([regra1, regra2, regra3, regra4, regra5])

Desfuzzificação

Na maioria das aplicações computacionais espera-se o retorno de um valor numérico que represente a ação tomada após a análise do cenário de entrada, para isso existe a etapa de desfuzzificação, que tem como função o processo contrário da fuzzificação. Nesta etapa o conjunto fuzzy agregado obtido na etapa de inferência precisa ser convertido em um valor numérico que será usado como controle da variável de saída que se quer agir. A desfuzzificação possui um impacto significativo no desempenho do controle fuzzy, assim existem diversos métodos para realizar a desfuzzificação (centroide, máximo dos máximos, média dos máximos e etc), sendo necessário escolher o método que melhor se adequa ao problema. O método mais usado é o método do centroide, que consiste em calcular o centro geométrico dos valores de saída fuzzy:

No exemplo do controle de distância vamos considerar o cenário onde o veículo trafega a 80km/h e a distância para o veículo da frente é de 20 metros, nesse caso a distância é considerada totalmente como mediana e a velocidade é considerada como pertencendo ao grupo de média e alta velocidade. É importante ter essa visão de quais conjuntos fuzzy a variável está pertencendo pois isso acionará as regras de acordo com os conjuntos pertentes.

Podemos ver que a entrada apresentada neste exemplo acionará as regras 2 e 5 que definimos anteriormente:

# Aplicando as variáveis de entrada
engine.input['velocidade'] = 80
engine.input['distancia'] = 20
# calcula a saída do sistema de controle fuzzy
engine.compute()
# retorna o valor de saída e o gráfico mostrando-o
print(engine.output['Freio'])
Freio.view(sim=engine)

Aplicando o método do centróide que mencionamos anteriormente temos que a pressão sobre o freio deverá ser de 54%

Conclusão

A modelagem fuzzy possui diversas aplicações nas áreas de controle e tomada de decisão de processos através do uso de uma linguagem natural ao invés de usar regras rígidas impostas por especialistas, que implica na perda da capacidade de condicionamento de soluções de problemas complexos. Assim, a lógica fuzzy aproxima o controle ou tomada de decisão do método de raciocínio humano, além de deixar transparente e interpretável o processo que levou desde a entrada da variável até a sua saída na forma de um controle.

--

--