用Python代码实战理解人工智能核心:从命题逻辑到模糊推理

人工智能理论常常因为抽象晦涩而让初学者望而生畏。当课本上充斥着符号化的逻辑表达式和数学公式时,很多学习者会陷入死记硬背的困境,却难以真正理解这些概念在实际中如何运作。本文将通过Python代码将这些抽象理论具象化,让你在编写和运行代码的过程中,直观感受人工智能核心思想的精妙之处。

1. 命题逻辑的Python实现

命题逻辑是人工智能最基础的形式化工具之一,它研究简单命题之间的逻辑关系。让我们用Python代码来构建一个简单的命题逻辑系统。

首先,我们定义命题的基本结构:

class Proposition:
    def __init__(self, symbol, value=None):
        self.symbol = symbol  # 命题符号,如P、Q等
        self.value = value    # 真值(True/False),未知时为None
    
    def evaluate(self):
        return self.value
    
    def __str__(self):
        return self.symbol

接下来实现逻辑连接词(与、或、非、蕴含等):

class And:
    def __init__(self, *propositions):
        self.propositions = propositions
    
    def evaluate(self):
        return all(p.evaluate() for p in self.propositions)
    
    def __str__(self):
        return "(" + " ∧ ".join(str(p) for p in self.propositions) + ")"

class Or:
    def __init__(self, *propositions):
        self.propositions = propositions
    
    def evaluate(self):
        return any(p.evaluate() for p in self.propositions)
    
    def __str__(self):
        return "(" + " ∨ ".join(str(p) for p in self.propositions) + ")"

class Not:
    def __init__(self, proposition):
        self.proposition = proposition
    
    def evaluate(self):
        return not self.proposition.evaluate()
    
    def __str__(self):
        return "¬" + str(self.proposition)

现在我们可以构建并验证一些命题逻辑表达式:

# 定义命题
P = Proposition("P", True)
Q = Proposition("Q", False)

# 构建复合命题
expr1 = And(P, Q)          # P ∧ Q
expr2 = Or(P, Q)           # P ∨ Q
expr3 = Not(And(P, Q))     # ¬(P ∧ Q)
expr4 = Or(Not(P), Q)      # ¬P ∨ Q

print(f"{expr1}: {expr1.evaluate()}")  # 输出: (P ∧ Q): False
print(f"{expr2}: {expr2.evaluate()}")  # 输出: (P ∨ Q): True
print(f"{expr3}: {expr3.evaluate()}")  # 输出: ¬(P ∧ Q): True
print(f"{expr4}: {expr4.evaluate()}")  # 输出: (¬P ∨ Q): False

通过这个简单的实现,我们可以直观地看到命题逻辑表达式如何求值,以及各种逻辑连接词的实际含义。

2. 谓词逻辑与归结原理的实现

谓词逻辑比命题逻辑更强大,它能够表达个体之间的关系。让我们实现一个简单的归结推理系统,这是自动定理证明的基础。

首先定义谓词和项:

class Term:
    def __init__(self, name, is_variable=False):
        self.name = name
        self.is_variable = is_variable
    
    def __eq__(self, other):
        return self.name == other.name and self.is_variable == other.is_variable
    
    def __str__(self):
        return self.name

class Predicate:
    def __init__(self, name, terms):
        self.name = name
        self.terms = terms  # Term对象的列表
    
    def __str__(self):
        return f"{self.name}({', '.join(str(t) for t in self.terms)})"

定义归结推理的核心算法:

def unify(x, y, substitution):
    if substitution is None:
        return None
    elif x == y:
        return substitution
    elif x.is_variable:
        return unify_var(x, y, substitution)
    elif y.is_variable:
        return unify_var(y, x, substitution)
    elif isinstance(x, Predicate) and isinstance(y, Predicate):
        if x.name != y.name or len(x.terms) != len(y.terms):
            return None
        for x_term, y_term in zip(x.terms, y.terms):
            substitution = unify(x_term, y_term, substitution)
            if substitution is None:
                return None
        return substitution
    else:
        return None

def unify_var(var, x, substitution):
    if var.name in substitution:
        return unify(substitution[var.name], x, substitution)
    elif x.is_variable and x.name in substitution:
        return unify(var, substitution[x.name], substitution)
    else:
        new_sub = substitution.copy()
        new_sub[var.name] = x
        return new_sub

def resolve(clause1, clause2):
    for literal1 in clause1:
        for literal2 in clause2:
            # 寻找互补文字
            if literal1.name == literal2.name and len(literal1.terms) == len(literal2.terms):
                # 尝试合一
                substitution = {}
                unified = True
                for t1, t2 in zip(literal1.terms, literal2.terms):
                    sub = unify(t1, t2, substitution)
                    if sub is None:
                        unified = False
                        break
                    substitution.update(sub)
                
                if unified:
                    # 应用替换并归结
                    new_clause = [l for l in clause1 if l != literal1] + [l for l in clause2 if l != literal2]
                    # 应用替换到新子句
                    for literal in new_clause:
                        for i in range(len(literal.terms)):
                            if literal.terms[i].is_variable and literal.terms[i].name in substitution:
                                literal.terms[i] = substitution[literal.terms[i].name]
                    return new_clause
    return None

现在我们可以用这个系统来解决一个简单的逻辑问题:

# 定义一些常量和变量
x = Term("x", is_variable=True)
y = Term("y", is_variable=True)
a = Term("a")
b = Term("b")

# 定义谓词
P = lambda terms: Predicate("P", terms)
Q = lambda terms: Predicate("Q", terms)
R = lambda terms: Predicate("R", terms)

# 示例:证明 ∃y ∀x P(x,y) ⇒ ∀x ∃y P(x,y)
# 将结论否定后与前提一起归结

# 前提:∃y ∀x P(x,y) 转化为子句 P(x,f(x))
# 结论否定:¬(∀x ∃y P(x,y)) 转化为 ∃x ∀y ¬P(x,y) 再转化为子句 ¬P(a,y)

clause1 = [P([x, Term("f(x)")])]  # P(x,f(x))
clause2 = [Not(P([a, y]))]        # ¬P(a,y)

# 归结过程
resolvent = resolve(clause1, clause2)
print("归结结果:", resolvent)  # 应该得到空子句,证明原命题成立

这个实现展示了如何通过代码来执行逻辑推理,帮助我们理解归结原理的实际运作方式。

3. 模糊逻辑系统的Python实现

模糊逻辑是处理不确定性和部分真实性的强大工具。让我们实现一个简单的模糊推理系统。

首先定义模糊集合和隶属函数:

class FuzzySet:
    def __init__(self, name, membership_function):
        self.name = name
        self.membership = membership_function  # 函数,接受输入返回隶属度[0,1]
    
    def __call__(self, x):
        return self.membership(x)

# 常用隶属函数
def triangular_mf(a, b, c):
    """三角形隶属函数,a < b < c"""
    return lambda x: max(0, min((x-a)/(b-a), (c-x)/(c-b), 1))

def trapezoidal_mf(a, b, c, d):
    """梯形隶属函数,a < b < c < d"""
    return lambda x: max(0, min((x-a)/(b-a), 1, (d-x)/(d-c)))

# 示例:定义温度"温暖"的模糊集
warm = FuzzySet("warm", triangular_mf(15, 25, 35))
print(f"20度的温暖度: {warm(20):.2f}")  # 输出: 20度的温暖度: 0.50
print(f"25度的温暖度: {warm(25):.2f}")  # 输出: 25度的温暖度: 1.00
print(f"35度的温暖度: {warm(35):.2f}")  # ��出: 35度的温暖度: 0.00

实现模糊规则和推理系统:

class FuzzyRule:
    def __init__(self, antecedents, consequent):
        self.antecedents = antecedents  # 前件列表 (FuzzySet, input_value) 或 (FuzzySet, input_variable_name)
        self.consequent = consequent    # 后件 (FuzzySet, output_variable_name)
    
    def evaluate(self, inputs):
        # 计算前件的隶属度(使用AND连接)
        strength = 1.0
        for ant in self.antecedents:
            if isinstance(ant[1], str):  # 如果是变量名
                input_value = inputs[ant[1]]
            else:  # 如果是固定值
                input_value = ant[1]
            strength = min(strength, ant[0](input_value))
        return (self.consequent[0], strength)

class FuzzySystem:
    def __init__(self):
        self.rules = []
    
    def add_rule(self, rule):
        self.rules.append(rule)
    
    def infer(self, inputs, defuzzify_method='centroid', num_points=100):
        # 执行所有规则,收集输出模糊集
        output_sets = {}
        for rule in self.rules:
            consequent_set, strength = rule.evaluate(inputs)
            if consequent_set.name not in output_sets:
                output_sets[consequent_set.name] = []
            output_sets[consequent_set.name].append((consequent_set, strength))
        
        # 对每个输出变量,聚合所有规则的结论
        results = {}
        for var_name, sets in output_sets.items():
            # 创建聚合的模糊集
            aggregated = {}
            # 假设所有集合有相同的定义域,这里简化处理
            # 在实际应用中需要更精细的处理
            min_x = 0
            max_x = 100
            step = (max_x - min_x) / num_points
            
            for x in [min_x + i*step for i in range(num_points+1)]:
                max_membership = 0
                for f_set, strength in sets:
                    max_membership = max(max_membership, min(f_set(x), strength))
                if max_membership > 0:
                    aggregated[x] = max_membership
            
            # 去模糊化
            if defuzzify_method == 'centroid':
                numerator = 0
                denominator = 0
                for x, mu in aggregated.items():
                    numerator += x * mu
                    denominator += mu
                results[var_name] = numerator / denominator if denominator != 0 else (min_x + max_x)/2
            elif defuzzify_method == 'max':
                max_x = None
                max_mu = -1
                for x, mu in aggregated.items():
                    if mu > max_mu or (mu == max_mu and (max_x is None or x < max_x)):
                        max_mu = mu
                        max_x = x
                results[var_name] = max_x if max_x is not None else (min_x + max_x)/2
        
        return results

使用这个模糊系统来解决一个实际问题:

# 定义输入模糊集
temperature = {
    "cold": FuzzySet("cold", trapezoidal_mf(-10, 0, 10, 20)),
    "warm": FuzzySet("warm", triangular_mf(15, 25, 35)),
    "hot": FuzzySet("hot", trapezoidal_mf(30, 40, 50, 60))
}

humidity = {
    "dry": FuzzySet("dry", trapezoidal_mf(0, 20, 30, 40)),
    "comfortable": FuzzySet("comfortable", triangular_mf(30, 50, 70)),
    "humid": FuzzySet("humid", trapezoidal_mf(60, 70, 80, 100))
}

# 定义输出模糊集(空调风速)
fan_speed = {
    "low": FuzzySet("low", trapezoidal_mf(0, 10, 20, 30)),
    "medium": FuzzySet("medium", triangular_mf(20, 50, 80)),
    "high": FuzzySet("high", trapezoidal_mf(70, 80, 90, 100))
}

# 创建模糊系统
system = FuzzySystem()

# 添加规则
system.add_rule(FuzzyRule([(temperature["cold"], "temp"), (humidity["dry"], "humidity")], (fan_speed["low"], "speed")))
system.add_rule(FuzzyRule([(temperature["cold"], "temp"), (humidity["comfortable"], "humidity")], (fan_speed["low"], "speed")))
system.add_rule(FuzzyRule([(temperature["warm"], "temp"), (humidity["dry"], "humidity")], (fan_speed["medium"], "speed")))
system.add_rule(FuzzyRule([(temperature["warm"], "temp"), (humidity["comfortable"], "humidity")], (fan_speed["medium"], "speed")))
system.add_rule(FuzzyRule([(temperature["hot"], "temp"), (humidity["dry"], "humidity")], (fan_speed["high"], "speed")))
system.add_rule(FuzzyRule([(temperature["hot"], "temp"), (humidity["comfortable"], "humidity")], (fan_speed["high"], "speed")))
system.add_rule(FuzzyRule([(temperature["hot"], "temp"), (humidity["humid"], "humidity")], (fan_speed["high"], "speed")))

# 进行推理
inputs = {"temp": 28, "humidity": 45}
result = system.infer(inputs)
print(f"温度为{inputs['temp']}度,湿度为{inputs['humidity']}%时,建议风扇速度: {result['speed']:.1f}%")

这个模糊系统展示了如何处理不确定的、模糊的输入,并产生合理的输出,这是许多智能控制系统的基础。

4. 遗传算法的Python实现

遗传算法是受自然选择启发的优化技术。让我们实现一个简单的遗传算法来解决函数优化问题。

首先定义遗传算法的基本组件:

import random
import numpy as np

def binary_to_float(binary, min_val, max_val, bits):
    """将二进制字符串转换为[min_val, max_val]范围内的浮点数"""
    int_val = int(binary, 2)
    return min_val + (max_val - min_val) * int_val / (2**bits - 1)

def float_to_binary(x, min_val, max_val, bits):
    """将浮点数转换为二进制字符串"""
    int_val = int((x - min_val) / (max_val - min_val) * (2**bits - 1))
    return format(int_val, f'0{bits}b')

class Individual:
    def __init__(self, chromosome, min_val, max_val, bits_per_var, fitness_func):
        self.chromosome = chromosome  # 二进制字符串
        self.min_val = min_val
        self.max_val = max_val
        self.bits_per_var = bits_per_var
        self.fitness_func = fitness_func
        self._fitness = None
    
    @property
    def fitness(self):
        if self._fitness is None:
            variables = []
            for i in range(0, len(self.chromosome), self.bits_per_var):
                binary = self.chromosome[i:i+self.bits_per_var]
                variables.append(binary_to_float(binary, self.min_val, self.max_val, self.bits_per_var))
            self._fitness = self.fitness_func(variables)
        return self._fitness
    
    def mutate(self, mutation_rate):
        """以一定概率翻转每个bit"""
        new_chromosome = []
        for bit in self.chromosome:
            if random.random() < mutation_rate:
                new_chromosome.append('1' if bit == '0' else '0')
            else:
                new_chromosome.append(bit)
        return Individual(''.join(new_chromosome), self.min_val, self.max_val, self.bits_per_var, self.fitness_func)
    
    @staticmethod
    def crossover(parent1, parent2, crossover_rate):
        """单点交叉"""
        if random.random() > crossover_rate or len(parent1.chromosome) <= 1:
            return parent1, parent2
        
        point = random.randint(1, len(parent1.chromosome)-1)
        child1 = parent1.chromosome[:point] + parent2.chromosome[point:]
        child2 = parent2.chromosome[:point] + parent1.chromosome[point:]
        return (
            Individual(child1, parent1.min_val, parent1.max_val, parent1.bits_per_var, parent1.fitness_func),
            Individual(child2, parent2.min_val, parent2.max_val, parent2.bits_per_var, parent2.fitness_func)
        )

class GeneticAlgorithm:
    def __init__(self, population_size, chromosome_length, min_val, max_val, bits_per_var, fitness_func):
        self.population_size = population_size
        self.chromosome_length = chromosome_length
        self.min_val = min_val
        self.max_val = max_val
        self.bits_per_var = bits_per_var
        self.fitness_func = fitness_func
        self.population = self._init_population()
    
    def _init_population(self):
        return [
            Individual(
                ''.join(random.choice('01') for _ in range(self.chromosome_length)),
                self.min_val,
                self.max_val,
                self.bits_per_var,
                self.fitness_func
            )
            for _ in range(self.population_size)
        ]
    
    def _select_parents(self, tournament_size=3):
        """锦标赛选择"""
        parents = []
        for _ in range(2):  # 选择两个父母
            tournament = random.sample(self.population, tournament_size)
            winner = max(tournament, key=lambda ind: ind.fitness)
            parents.append(winner)
        return parents
    
    def evolve(self, generations, crossover_rate=0.8, mutation_rate=0.01, elitism=1):
        best_individuals = []
        
        for gen in range(generations):
            # 评估当前种群
            self.population.sort(key=lambda ind: ind.fitness, reverse=True)
            best_individuals.append(self.population[0])
            
            # 创建新一代
            new_population = []
            
            # 精英主义:保留最好的个体
            new_population.extend(self.population[:elitism])
            
            # 生成剩余个体
            while len(new_population) < self.population_size:
                # 选择父母
                parent1, parent2 = self._select_parents()
                
                # 交叉
                child1, child2 = Individual.crossover(parent1, parent2, crossover_rate)
                
                # 变异
                child1 = child1.mutate(mutation_rate)
                child2 = child2.mutate(mutation_rate)
                
                # 添加到新种群
                new_population.append(child1)
                if len(new_population) < self.population_size:
                    new_population.append(child2)
            
            self.population = new_population
        
        # 返回所有代中的最佳个体
        return max(best_individuals, key=lambda ind: ind.fitness)

使用这个遗传算法来优化一个函数:

# 定义要优化的函数(寻找最大值)
def sphere_function(variables):
    # 多维球面函数,最小值在(0,0,...,0)
    return -sum(x**2 for x in variables)  # 取负值因为我们寻找最大值

# 设置遗传算法参数
num_variables = 2  # 优化2维函数
bits_per_var = 16  # 每个变量用16位表示
min_val = -5.0     # 变量最小值
max_val = 5.0      # 变量最大值
chromosome_length = num_variables * bits_per_var
population_size = 50
generations = 100

# 创建并运行遗传算法
ga = GeneticAlgorithm(
    population_size=population_size,
    chromosome_length=chromosome_length,
    min_val=min_val,
    max_val=max_val,
    bits_per_var=bits_per_var,
    fitness_func=sphere_function
)

best_individual = ga.evolve(generations)

# 解码最佳个体
best_variables = []
for i in range(0, len(best_individual.chromosome), bits_per_var):
    binary = best_individual.chromosome[i:i+bits_per_var]
    best_variables.append(binary_to_float(binary, min_val, max_val, bits_per_var))

print(f"最佳解: {best_variables}, 适应度: {best_individual.fitness:.6f}")
print(f"理论最优解: [0, 0], 适应度: 0")

这个实现展示了遗传算法如何通过模拟自然选择过程来寻找复杂问题的优化解,是解决许多工程优化问题的有力工具。

更多推荐