第13章:Agent 的持续学习与适应 AI Agent 的一个关键特性是能够从经验中学习并适应新的环境和任务。本章将探讨实现持续学习和适应的各种技术和策略。 13.1 在线学习机制 在线学习允许 Agent 在接收新数据时实时更新其模型,而无需重新训练整个模型。 13.1.1 增量学习算法 增量学习算法使 Agent 能够逐步学习新信息,而不会忘记之前学到的知识。 示例(简单的增量学习模型): 13.1.2 概念漂移检测 概念漂移检测帮助 Agent 识别数据分布的变化,从而触发模型更新。 示例(概念漂移检测器): 13.1.3 模型更新策略 设计有效的策略来决定何时以及如何更新模型,以适应新的数据模式。 示例(自适应模型更新器): 13.
AI Agent 的一个关键特性是能够从经验中学习并适应新的环境和任务。本章将探讨实现持续学习和适应的各种技术和策略。
在线学习允许 Agent 在接收新数据时实时更新其模型,而无需重新训练整个模型。
增量学习算法使 Agent 能够逐步学习新信息,而不会忘记之前学到的知识。
示例(简单的增量学习模型):
import numpy as np from sklearn.base import BaseEstimator, ClassifierMixin class IncrementalLearner(BaseEstimator, ClassifierMixin): def __init__(self, learning_rate=0.01): self.learning_rate = learning_rate self.weights = None self.classes = None def partial_fit(self, X, y, classes=None): if self.classes is None: self.classes = np.unique(y) if self.weights is None: self.weights = np.zeros((len(self.classes), X.shape[1])) for xi, yi in zip(X, y): true_class = np.where(self.classes == yi)[0][0] y_pred = np.argmax(np.dot(self.weights, xi)) if y_pred != true_class: self.weights[true_class] += self.learning_rate * xi self.weights[y_pred] -= self.learning_rate * xi return self def predict(self, X): if self.weights is None: raise ValueError("Model not fitted yet.") return self.classes[np.argmax(np.dot(X, self.weights.T), axis=1)] # 使用示例 np.random.seed(42) X_stream = np.random.randn(1000, 5) y_stream = np.random.randint(0, 3, 1000) model = IncrementalLearner(learning_rate=0.1) # 模拟在线学习 batch_size = 10 for i in range(0, len(X_stream), batch_size): X_batch = X_stream[i:i+batch_size] y_batch = y_stream[i:i+batch_size] model.partial_fit(X_batch, y_batch, classes=np.unique(y_stream)) if i % 200 == 0: accuracy = np.mean(model.predict(X_batch) == y_batch) print(f"Batch {i//batch_size}, Accuracy: {accuracy:.4f}") # 最终评估 final_accuracy = np.mean(model.predict(X_stream) == y_stream) print(f"Final Accuracy: {final_accuracy:.4f}")
概念漂移检测帮助 Agent 识别数据分布的变化,从而触发模型更新。
示例(概念漂移检测器):
import numpy as np from scipy import stats class ConceptDriftDetector: def __init__(self, window_size=100, alpha=0.05): self.window_size = window_size self.alpha = alpha self.reference_window = [] self.current_window = [] def add_sample(self, sample): if len(self.reference_window) < self.window_size: self.reference_window.append(sample) else: self.current_window.append(sample) if len(self.current_window) == self.window_size: drift_detected = self.check_for_drift() if drift_detected: self.reference_window = self.current_window self.current_window = [] return True else: self.current_window.pop(0) return False def check_for_drift(self): t_statistic, p_value = stats.ttest_ind(self.reference_window, self.current_window) return p_value < self.alpha # 使用示例 np.random.seed(42) detector = ConceptDriftDetector(window_size=50, alpha=0.01) # 模拟数据流,在中间引入概念漂移 data_stream = np.concatenate([ np.random.normal(0, 1, 500), # 初始概念 np.random.normal(2, 1, 500) # 漂移后的概念 ]) drift_points = [] for i, sample in enumerate(data_stream): if detector.add_sample(sample): drift_points.append(i) print(f"Concept drift detected at sample {i}") print(f"Total drift points detected: {len(drift_points)}")
设计有效的策略来决定何时以及如何更新模型,以适应新的数据模式。
示例(自适应模型更新器):
import numpy as np from sklearn.base import BaseEstimator, ClassifierMixin from sklearn.tree import DecisionTreeClassifier class AdaptiveModelUpdater(BaseEstimator, ClassifierMixin): def __init__(self, base_estimator=None, window_size=100, drift_threshold=0.1): self.base_estimator = base_estimator or DecisionTreeClassifier() self.window_size = window_size self.drift_threshold = drift_threshold self.X_window = [] self.y_window = [] self.performance_history = [] def partial_fit(self, X, y, classes=None): for xi, yi in zip(X, y): self.X_window.append(xi) self.y_window.append(yi) if len(self.X_window) >= self.window_size: if not hasattr(self, 'classes_'): self.classes_ = np.unique(self.y_window) # 评估当前模型性能 if hasattr(self, 'base_estimator_'): current_performance = self.base_estimator_.score(self.X_window, self.y_window) self.performance_history.append(current_performance) # 检测性能下降 if len(self.performance_history) > 1: performance_change = self.performance_history[-1] - self.performance_history[-2] if performance_change < -self.drift_threshold: # 重新训练模型 self.base_estimator_ = clone(self.base_estimator) self.base_estimator_.fit(self.X_window, self.y_window) print("Model updated due to performance drift") else: # 初始化模型 self.base_estimator_ = clone(self.base_estimator) self.base_estimator_.fit(self.X_window, self.y_window) # 清空窗口 self.X_window = [] self.y_window = [] return self def predict(self, X): if not hasattr(self, 'base_estimator_'): raise ValueError("Model not fitted yet.") return self.base_estimator_.predict(X) # 使用示例 np.random.seed(42) X_stream = np.vstack([ np.random.randn(500, 5), np.random.randn(500, 5) + 2 # 引入概念漂移 ]) y_stream = np.hstack([ np.random.randint(0, 3, 500), np.random.randint(3, 5, 500) # 新类别 ]) model = AdaptiveModelUpdater(window_size=100, drift_threshold=0.05) # 模拟在线学习 batch_size = 10 for i in range(0, len(X_stream), batch_size): X_batch = X_stream[i:i+batch_size] y_batch = y_stream[i:i+batch_size] model.partial_fit(X_batch, y_batch) if i % 100 == 0: accuracy = model.score(X_batch, y_batch) print(f"Batch {i//batch_size}, Accuracy: {accuracy:.4f}") # 最终评估 final_accuracy = model.score(X_stream, y_stream) print(f"Final Accuracy: {final_accuracy:.4f}")
主动学习使 Agent 能够识别最有价值的学习机会,从而更有效地利用资源。
通过选择模型最不确定的样本进行标注,可以快速提高模型性能。
示例(不确定性采样器):
import numpy as np from sklearn.base import BaseEstimator, ClassifierMixin from sklearn.ensemble import RandomForestClassifier class UncertaintySampler(BaseEstimator, ClassifierMixin): def __init__(self, base_estimator=None, n_samples=10): self.base_estimator = base_estimator or RandomForestClassifier() self.n_samples = n_samples def fit(self, X, y): self.base_estimator.fit(X, y) return self def predict(self, X): return self.base_estimator.predict(X) def predict_proba(self, X): return self.base_estimator.predict_proba(X) def query(self, X_pool): probas = self.predict_proba(X_pool) uncertainties = 1 - np.max(probas, axis=1) return np.argsort(uncertainties)[-self.n_samples:] # 使用示例 np.random.seed(42) X_pool = np.random.randn(1000, 5) y_pool = np.random.randint(0, 3, 1000) # 初始训练集 X_train = X_pool[:100] y_train = y_pool[:100] # 剩余的池 X_remain = X_pool[100:] y_remain = y_pool[100:] model = UncertaintySampler(n_samples=10) model.fit(X_train, y_train) for i in range(5): # 5轮主动学习 # 查询最不确定的样本 query_indices = model.query(X_remain) # 添加到训练集 X_train = np.vstack([X_train, X_remain[query_indices]]) y_train = np.hstack([y_train, y_remain[query_indices]]) # 从池中移除 X_remain = np.delete(X_remain, query_indices, axis=0) y_remain = np.delete(y_remain, query_indices) # 重新训练模型 model.fit(X_train, y_train) # 评估 accuracy = model.score(X_pool, y_pool) print(f"Round {i+1}, Accuracy: {accuracy:.4f}, Training set size: {len(y_train)}")
选择多样化的样本可以帮助模型更好地覆盖整个特征空间。
示例(多样性采样器):
import numpy as np from sklearn.cluster import KMeans class DiversitySampler: def __init__(self, n_samples=10): self.n_samples = n_samples def query(self, X_pool, X_train): # 使用 K-means 聚类来选择多样化的样本 n_clusters = min(self.n_samples, len(X_pool)) kmeans = KMeans(n_clusters=n_clusters, random_state=42) cluster_labels = kmeans.fit_predict(X_pool) selected_indices = [] for cluster in range(n_clusters): cluster_points = np.where(cluster_labels == cluster)[0] if len(cluster_points) > 0: # 选择离聚类中心最近的点 center = kmeans.cluster_centers_[cluster] distances = np.linalg.norm(X_pool[cluster_points] - center, axis=1) selected_index = cluster_points[np.argmin(distances)] selected_indices.append(selected_index) return selected_indices # 使用示例 np.random.seed(42) X_pool = np.random.randn(1000, 5) y_pool = np.random.randint(0, 3, 1000) # 初始训练集 X_train = X_pool[:100] y_train = y_pool[:100] # 剩余的池 X_remain = X_pool[100:] y_remain = y_pool[100:] sampler = DiversitySampler(n_samples=10) model = RandomForestClassifier(random_state=42) for i in range(5): # 5轮主动学习 # 查询多样化的样本 query_indices = sampler.query(X_remain, X_train) # 添加到训练集 X_train = np.vstack([X_train, X_remain[query_indices]]) y_train = np.hstack([y_train, y_remain[query_indices]]) # 从池中移除 X_remain = np.delete(X_remain, query_indices, axis=0) y_remain = np.delete(y_remain, query_indices) # 训练模型 model.fit(X_train, y_train) # 评估 accuracy = model.score(X_pool, y_pool) print(f"Round {i+1}, Accuracy: {accuracy:.4f}, Training set size: {len(y_train)}")
选择能够代表整个数据分布的样本,以提高模型的泛化能力。
示例(代表性采样器):
import numpy as np from sklearn.metrics import pairwise_distances class RepresentativeSampler: def __init__(self, n_samples=10): self.n_samples = n_samples def query(self, X_pool): # 计算样本间的距离矩阵 distances = pairwise_distances(X_pool) # 初始化已选择的样本集 selected = [] # 选择第一个样本(距离所有其他样本最近的点) first = np.argmin(distances.sum(axis=1)) selected.append(first) # 迭代选择剩余的样本 for _ in range(1, self.n_samples): # 计算每个未选择样本到已选择样本集的最小距离 min_distances = distances[:, selected].min(axis=1) # 选择具有最大最小距离的样本 next_sample = np.argmax(min_distances) selected.append(next_sample) return selected # 使用示例 np.random.seed(42) X_pool = np.random.randn(1000, 5) y_pool = np.random.randint(0, 3, 1000) # 初始训练集 X_train = X_pool[:100] y_train = y_pool[:100] # 剩余的池 X_remain = X_pool[100:] y_remain = y_pool[100:] sampler = RepresentativeSampler(n_samples=10) model = RandomForestClassifier(random_state=42) for i in range(5): # 5轮主动学习 # 查询代表性样本 query_indices = sampler.query(X_remain) # 添加到训练集 X_train = np.vstack([X_train, X_remain[query_indices]]) y_train = np.hstack([y_train, y_remain[query_indices]]) # 从池中移除 X_remain = np.delete(X_remain, query_indices, axis=0) y_remain = np.delete(y_remain, query_indices) # 训练模型 model.fit(X_train, y_train) # 评估 accuracy = model.score(X_pool, y_pool) print(f"Round {i+1}, Accuracy: {accuracy:.4f}, Training set size: {len(y_train)}")
这些示例展示了 Agent 持续学习和适应的不同策略。在实际应用中,这些方法可能需要更复杂的实现:
此外,在实施这些持续学习和适应策略时,还需要考虑:
通过实施这些持续学习和适应策略,我们可以开发出能够不断进化和改进的 AI Agent,使其能够更好地应对复杂和动态的环境。这不仅提高了 Agent 的性能和适应性,还增强了其在实际应用中的实用性和可靠性。
迁移学习和域适应技术使 Agent 能够将在一个任务或领域学到的知识应用到新的、相关的任务或领域中。
跨域知识迁移允许 Agent 利用在源域中学到的知识来提高在目标域中的性能。
示例(简单的迁移学习模型):
import numpy as np from sklearn.base import BaseEstimator, ClassifierMixin from sklearn.neural_network import MLPClassifier class TransferLearningClassifier(BaseEstimator, ClassifierMixin): def __init__(self, hidden_layer_sizes=(100,), learning_rate_init=0.001): self.hidden_layer_sizes = hidden_layer_sizes self.learning_rate_init = learning_rate_init self.source_model = None self.target_model = None def fit_source(self, X, y): self.source_model = MLPClassifier(hidden_layer_sizes=self.hidden_layer_sizes, learning_rate_init=self.learning_rate_init) self.source_model.fit(X, y) return self def transfer_and_fit(self, X, y): if self.source_model is None: raise ValueError("Source model not fitted. Call fit_source first.") # 初始化目标模型,使用源模型的权重 self.target_model = MLPClassifier(hidden_layer_sizes=self.hidden_layer_sizes, learning_rate_init=self.learning_rate_init, warm_start=True) self.target_model.coefs_ = self.source_model.coefs_ self.target_model.intercepts_ = self.source_model.intercepts_ # 在目标数据上微调模型 self.target_model.fit(X, y) return self def predict(self, X): if self.target_model is None: raise ValueError("Target model not fitted. Call transfer_and_fit first.") return self.target_model.predict(X) # 使用示例 np.random.seed(42) # 源域数据(简单的二分类问题) X_source = np.random.randn(1000, 10) y_source = (X_source[:, 0] + X_source[:, 1] > 0).astype(int) # 目标域数据(相似但略有不同的问题) X_target = np.random.randn(200, 10) y_target = (X_target[:, 0] + X_target[:, 1] + 0.1 * X_target[:, 2] > 0).astype(int) # 创建和训练迁移学习模型 transfer_model = TransferLearningClassifier(hidden_layer_sizes=(50, 25)) transfer_model.fit_source(X_source, y_source) transfer_model.transfer_and_fit(X_target[:100], y_target[:100]) # 评估 accuracy = transfer_model.score(X_target[100:], y_target[100:]) print(f"Transfer Learning Model Accuracy: {accuracy:.4f}") # 比较:在目标数据上从头训练的模型 baseline_model = MLPClassifier(hidden_layer_sizes=(50, 25)) baseline_model.fit(X_target[:100], y_target[:100]) baseline_accuracy = baseline_model.score(X_target[100:], y_target[100:]) print(f"Baseline Model Accuracy: {baseline_accuracy:.4f}")
零样本和少样本学习技术使 Agent 能够在只有很少或没有标记数据的情况下学习新任务。
示例(简化的少样本学习模型):
import numpy as np from sklearn.base import BaseEstimator, ClassifierMixin from sklearn.metrics.pairwise import cosine_similarity class FewShotLearner(BaseEstimator, ClassifierMixin): def __init__(self, n_support=5): self.n_support = n_support self.support_set = {} def fit(self, X, y): unique_classes = np.unique(y) for cls in unique_classes: class_samples = X[y == cls] if len(class_samples) >= self.n_support: self.support_set[cls] = class_samples[:self.n_support] else: self.support_set[cls] = class_samples return self def predict(self, X): if not self.support_set: raise ValueError("Model not fitted yet.") predictions = [] for x in X: similarities = {} for cls, support_samples in self.support_set.items(): similarity = cosine_similarity([x], support_samples).mean() similarities[cls] = similarity predictions.append(max(similarities, key=similarities.get)) return np.array(predictions) # 使用示例 np.random.seed(42) # 生成一些模拟数据 def generate_data(n_samples, n_features, n_classes): X = np.random.randn(n_samples, n_features) y = np.random.randint(0, n_classes, n_samples) return X, y # 训练数据(每个类别只有少量样本) X_train, y_train = generate_data(n_samples=50, n_features=10, n_classes=5) # 测试数据 X_test, y_test = generate_data(n_samples=100, n_features=10, n_classes=5) # 创建和训练少样本学习模型 few_shot_model = FewShotLearner(n_support=3) few_shot_model.fit(X_train, y_train) # 评估 accuracy = few_shot_model.score(X_test, y_test) print(f"Few-Shot Learning Model Accuracy: {accuracy:.4f}")
元学习使 Agent 能够学习如何学习,从而在面对新任务时能够更快地适应。
示例(简化的元学习模型):
import numpy as np from sklearn.base import BaseEstimator, ClassifierMixin from sklearn.linear_model import SGDClassifier class MetaLearner(BaseEstimator, ClassifierMixin): def __init__(self, n_inner_steps=5, alpha=0.1): self.n_inner_steps = n_inner_steps self.alpha = alpha self.meta_model = SGDClassifier(loss='log', learning_rate='constant', eta0=0.01) def fit(self, tasks): meta_X, meta_y = [], [] for X, y in tasks: initial_weights = np.random.randn(X.shape[1]) adapted_weights = self._inner_loop_adapt(X, y, initial_weights) meta_X.append(adapted_weights - initial_weights) meta_y.append(initial_weights) self.meta_model.fit(meta_X, meta_y) return self def _inner_loop_adapt(self, X, y, weights): for _ in range(self.n_inner_steps): grad = self._compute_gradient(X, y, weights) weights -= self.alpha * grad return weights def _compute_gradient(self, X, y, weights): y_pred = 1 / (1 + np.exp(-np.dot(X, weights))) return np.dot(X.T, y_pred - y) / len(y) def predict(self, X, n_adapt_steps=1): initial_weights = self.meta_model.predict([np.zeros(X.shape[1])])[0] adapted_weights = self._inner_loop_adapt(X, np.zeros(len(X)), initial_weights) return (np.dot(X, adapted_weights) > 0).astype(int) # 使用示例 np.random.seed(42) # 生成一组相关但不同的任务 def generate_tasks(n_tasks, n_samples, n_features): tasks = [] for _ in range(n_tasks): X = np.random.randn(n_samples, n_features) weights = np.random.randn(n_features) y = (np.dot(X, weights) > 0).astype(int) tasks.append((X, y)) return tasks # 生成训练和测试任务 train_tasks = generate_tasks(n_tasks=100, n_samples=20, n_features=5) test_tasks = generate_tasks(n_tasks=20, n_samples=20, n_features=5) # 创建和训练元学习模型 meta_learner = MetaLearner() meta_learner.fit(train_tasks) # 评估 accuracies = [] for X, y in test_tasks: y_pred = meta_learner.predict(X) accuracies.append(np.mean(y_pred == y)) print(f"Meta-Learning Model Average Accuracy: {np.mean(accuracies):.4f}")
这些示例展示了迁移学习、域适应和元学习的基本概念。在实际应用中,这些方法通常需要更复杂和高级的实现:
此外,在实施这些高级学习技术时,还需要考虑:
通过结合这些先进的学习技术,我们可以开发出更加灵活和适应性强的 AI Agent,能够快速学习新任务,适应新环境,并在有限的数据或资源下表现出色。这些能力对于创建真正通用和实用的 AI 系统至关重要。
自监督学习允许 Agent 从未标记的数据中学习有用的表示,这在大规模数据可用但标签稀缺的情况下特别有价值。
对比学习通过学习区分相似和不相似的样本对来学习有用的表示。
示例(简单的对比学习模型):
import numpy as np import torch import torch.nn as nn import torch.optim as optim class SimpleEncoder(nn.Module): def __init__(self, input_dim, output_dim): super().__init__() self.encoder = nn.Sequential( nn.Linear(input_dim, 64), nn.ReLU(), nn.Linear(64, output_dim) ) def forward(self, x): return self.encoder(x) class ContrastiveLearner: def __init__(self, input_dim, output_dim, temperature=0.5): self.encoder = SimpleEncoder(input_dim, output_dim) self.temperature = temperature self.optimizer = optim.Adam(self.encoder.parameters(), lr=0.001) def generate_pair(self, x): # 生成正样本对(这里简单地加入少量噪声) noise = torch.randn_like(x) * 0.1 return x + noise def compute_loss(self, z1, z2): # 计算 NT-Xent 损失 z1 = nn.functional.normalize(z1, dim=1) z2 = nn.functional.normalize(z2, dim=1) similarity_matrix = torch.matmul(z1, z2.T) positives = torch.diag(similarity_matrix) negatives = similarity_matrix - torch.eye(z1.shape[0]) logits = torch.cat([positives, negatives.view(-1)]) / self.temperature labels = torch.zeros(logits.shape[0], dtype=torch.long) labels[:z1.shape[0]] = 1 return nn.functional.cross_entropy(logits.unsqueeze(0), labels.unsqueeze(0)) def train_step(self, x): self.optimizer.zero_grad() x_pair = self.generate_pair(x) z1 = self.encoder(x) z2 = self.encoder(x_pair) loss = self.compute_loss(z1, z2) loss.backward() self.optimizer.step() return loss.item() # 使用示例 np.random.seed(42) torch.manual_seed(42) # 生成一些模拟数据 X = torch.randn(1000, 10) # 创建和训练对比学习模型 contrastive_learner = ContrastiveLearner(input_dim=10, output_dim=5) n_epochs = 100 for epoch in range(n_epochs): total_loss = 0 for i in range(0, len(X), 32): batch = X[i:i+32] loss = contrastive_learner.train_step(batch) total_loss += loss if (epoch + 1) % 10 == 0: print(f"Epoch {epoch+1}/{n_epochs}, Loss: {total_loss/len(X):.4f}") # 使用训练好的编码器提取特征 encoded_features = contrastive_learner.encoder(X).detach().numpy() print("Encoded features shape:", encoded_features.shape)
掩码预测任务,如BERT中使用的方法,通过预测输入中被掩盖的部分来学习上下文相关的表示。
示例(简化的掩码预测模型):
import numpy as np import torch import torch.nn as nn import torch.optim as optim class SimpleMaskedLanguageModel(nn.Module): def __init__(self, vocab_size, embed_dim, hidden_dim): super().__init__() self.embedding = nn.Embedding(vocab_size, embed_dim) self.transformer = nn.TransformerEncoderLayer(d_model=embed_dim, nhead=4) self.fc = nn.Linear(embed_dim, vocab_size) def forward(self, x): x = self.embedding(x) x = self.transformer(x) return self.fc(x) class MaskedLanguageModelTrainer: def __init__(self, vocab_size, embed_dim, hidden_dim): self.model = SimpleMaskedLanguageModel(vocab_size, embed_dim, hidden_dim) self.optimizer = optim.Adam(self.model.parameters(), lr=0.001) self.criterion = nn.CrossEntropyLoss() def create_masked_input(self, x, mask_prob=0.15): mask = torch.rand(x.shape) < mask_prob masked_x = x.clone() masked_x[mask] = vocab_size - 1 # 假设最后一个 token 是 [MASK] return masked_x, mask def train_step(self, x): self.optimizer.zero_grad() masked_x, mask = self.create_masked_input(x) outputs = self.model(masked_x) loss = self.criterion(outputs[mask], x[mask]) loss.backward() self.optimizer.step() return loss.item() # 使用示例 np.random.seed(42) torch.manual_seed(42) # 生成一些模拟的文本数据 vocab_size = 1000 seq_length = 20 n_samples = 1000 X = torch.randint(0, vocab_size-1, (n_samples, seq_length)) # 创建和训练掩码语言模型 mlm_trainer = MaskedLanguageModelTrainer(vocab_size=vocab_size, embed_dim=64, hidden_dim=128) n_epochs = 50 for epoch in range(n_epochs): total_loss = 0 for i in range(0, len(X), 32): batch = X[i:i+32] loss = mlm_trainer.train_step(batch) total_loss += loss if (epoch + 1) % 5 == 0: print(f"Epoch {epoch+1}/{n_epochs}, Loss: {total_loss/len(X):.4f}") # 使用训练好的模型进行预测 test_sequence = torch.randint(0, vocab_size-1, (1, seq_length)) masked_sequence, mask = mlm_trainer.create_masked_input(test_sequence) with torch.no_grad(): predictions = mlm_trainer.model(masked_sequence) predicted_tokens = torch.argmax(predictions[mask], dim=1) print("Original sequence:", test_sequence[0]) print("Masked sequence:", masked_sequence[0]) print("Predicted tokens:", predicted_tokens)
数据增强技术通过创建输入数据的变体来增加训练样本的多样性,从而提高模型的泛化能力。
示例(图像数据增强器):
import numpy as np from PIL import Image import torchvision.transforms as transforms class ImageDataAugmenter: def __init__(self): self.transforms = transforms.Compose([ transforms.RandomHorizontalFlip(), transforms.RandomRotation(10), transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1), transforms.RandomResizedCrop(224, scale=(0.8, 1.0)), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) def augment(self, image): return self.transforms(image) # 使用示例 np.random.seed(42) # 创建一个模拟的图像(这里使用随机数据) image = Image.fromarray(np.random.randint(0, 255, (224, 224, 3), dtype=np.uint8)) augmenter = ImageDataAugmenter() # 生成多个增强版本 n_augmentations = 5 augmented_images = [augmenter.augment(image) for _ in range(n_augmentations)] print(f"Generated {n_augmentations} augmented versions of the image.") print(f"Augmented image shape: {augmented_images[0].shape}")
这些示例展示了自监督学习的几种常见技术。在实际应用中,这些方法通常需要更复杂和大规模的实现:
此外,在实施这些自监督学习技术时,还需要考虑:
通过结合这些自监督学习技术,我们可以开发出能够有效利用大量未标记数据的 AI Agent,从而在标签稀缺的情况下也能学习到有用的表示。这对于构建更加通用和强大的 AI 系统至关重要,特别是在处理复杂、高维度的数据时。
终身学习系统旨在持续学习新知识和技能,同时保持先前学到的能力。设计这样的系统需要解决几个关键挑战。
在终身学习中,需要在学习新知识(可塑性)和保持旧知识(稳定性)之间取得平衡。
示例(具有可塑性-稳定性平衡的简单神经网络):
import numpy as np import torch import torch.nn as nn import torch.optim as optim class PlasticStableNetwork(nn.Module): def __init__(self, input_size, hidden_size, output_size, plasticity_rate=0.1): super().__init__() self.fc1 = nn.Linear(input_size, hidden_size) self.fc2 = nn.Linear(hidden_size, output_size) self.plasticity_rate = plasticity_rate self.old_params = None def forward(self, x): x = torch.relu(self.fc1(x)) x = self.fc2(x) return x def update_old_params(self): self.old_params = [p.clone().detach() for p in self.parameters()] def plastic_stable_update(self): if self.old_params is not None: for param, old_param in zip(self.parameters(), self.old_params): param.data = (1 - self.plasticity_rate) * old_param + self.plasticity_rate * param.data class LifelongLearner: def __init__(self, input_size, hidden_size, output_size, plasticity_rate=0.1): self.model = PlasticStableNetwork(input_size, hidden_size, output_size, plasticity_rate) self.optimizer = optim.Adam(self.model.parameters(), lr=0.001) self.criterion = nn.MSELoss() def train_task(self, X, y, epochs=100): self.model.update_old_params() for epoch in range(epochs): self.optimizer.zero_grad() outputs = self.model(X) loss = self.criterion(outputs, y) loss.backward() self.optimizer.step() self.model.plastic_stable_update() if (epoch + 1) % 10 == 0: print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}') # 使用示例 np.random.seed(42) torch.manual_seed(42) input_size, hidden_size, output_size = 10, 20, 5 learner = LifelongLearner(input_size, hidden_size, output_size) # 模拟多个连续任务 for task in range(3): print(f"\nTraining on Task {task + 1}") X = torch.randn(100, input_size) y = torch.randn(100, output_size) learner.train_task(X, y, epochs=50) # 测试在之前任务上的表现 X_test = torch.randn(10, input_size) y_pred = learner.model(X_test) print("\nPredictions on new data:") print(y_pred)
灾难性遗忘是指在学习新任务时,模型在先前任务上的性能急剧下降。缓解这个问题是终身学习系统的关键挑战之一。
示例(使用弹性权重整合的灾难性遗忘缓解):
import numpy as np import torch import torch.nn as nn import torch.optim as optim class EWCNetwork(nn.Module): def __init__(self, input_size, hidden_size, output_size): super().__init__() self.fc1 = nn.Linear(input_size, hidden_size) self.fc2 = nn.Linear(hidden_size, output_size) self.fisher_information = {} self.old_params = {} def forward(self, x): x = torch.relu(self.fc1(x)) x = self.fc2(x) return x def calculate_fisher(self, data_loader, num_samples=100): self.eval() fisher = {n: torch.zeros_like(p) for n, p in self.named_parameters()} for input, _ in data_loader: self.zero_grad() output = self(input).log_softmax(dim=1) label = output.max(1)[1].view(-1) loss = nn.functional.nll_loss(output, label) loss.backward() for n, p in self.named_parameters(): fisher[n] += p.grad.data ** 2 / num_samples self.fisher_information = fisher self.old_params = {n: p.clone().detach() for n, p in self.named_parameters()} class EWCLearner: def __init__(self, input_size, hidden_size, output_size, ewc_lambda=100): self.model = EWCNetwork(input_size, hidden_size, output_size) self.optimizer = optim.Adam(self.model.parameters(), lr=0.001) self.criterion = nn.MSELoss() self.ewc_lambda = ewc_lambda def ewc_loss(self): loss = 0 for n, p in self.model.named_parameters(): if n in self.model.fisher_information: loss += (self.model.fisher_information[n] * (p - self.model.old_params[n]) ** 2).sum() return self.ewc_lambda * loss def train_task(self, X, y, epochs=100): for epoch in range(epochs): self.optimizer.zero_grad() outputs = self.model(X) loss = self.criterion(outputs, y) + self.ewc_loss() loss.backward() self.optimizer.step() if (epoch + 1) % 10 == 0: print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}') # 更新Fisher信息 data_loader = torch.utils.data.DataLoader(torch.utils.data.TensorDataset(X, y), batch_size=10, shuffle=True) self.model.calculate_fisher(data_loader) # 使用示例 np.random.seed(42) torch.manual_seed(42) input_size, hidden_size, output_size = 10, 20, 5 learner = EWCLearner(input_size, hidden_size, output_size) # 模拟多个连续任务 for task in range(3): print(f"\nTraining on Task {task + 1}") X = torch.randn(100, input_size) y = torch.randn(100, output_size) learner.train_task(X, y, epochs=50) # 测试在之前任务上的表现 X_test = torch.randn(10, input_size) y_pred = learner.model(X_test) print("\nPredictions on new data:") print(y_pred)
有效的终身学习系统需要能够积累新知识并将其与现有知识整合。
示例(使用渐进式神经网络的知识积累系统):
import numpy as np import torch import torch.nn as nn import torch.optim as optim class ProgressiveColumn(nn.Module): def __init__(self, input_size, hidden_size, output_size, prev_columns=None): super().__init__() self.fc1 = nn.Linear(input_size, hidden_size) lateral_connections = 0 if prev_columns is None else len(prev_columns) * hidden_size self.fc2 = nn.Linear(hidden_size + lateral_connections, output_size) self.prev_columns = prev_columns def forward(self, x): h1 = torch.relu(self.fc1(x)) if self.prev_columns: prev_activations = [torch.relu(col.fc1(x)) for col in self.prev_columns] h1 = torch.cat([h1] + prev_activations, dim=1) return self.fc2(h1) class ProgressiveNetwork: def __init__(self, input_size, hidden_size, output_size): self.input_size = input_size self.hidden_size = hidden_size self.output_size = output_size self.columns = [] def add_column(self): new_column = ProgressiveColumn(self.input_size, self.hidden_size, self.output_size, self.columns) self.columns.append(new_column) return new_column def forward(self, x, task_id): if task_id >= len(self.columns): raise ValueError("Invalid task ID") return self.columns[task_id](x) class ProgressiveLearner: def __init__(self, input_size, hidden_size, output_size): self.network = ProgressiveNetwork(input_size, hidden_size, output_size) self.criterion = nn.MSELoss() def train_task(self, X, y, epochs=100): column = self.network.add_column() optimizer = optim.Adam(column.parameters(), lr=0.001) for epoch in range(epochs): optimizer.zero_grad() outputs = column(X) loss = self.criterion(outputs, y) loss.backward() optimizer.step() if (epoch + 1) % 10 == 0: print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}') def predict(self, X, task_id): return self.network.forward(X, task_id) # 使用示例 np.random.seed(42) torch.manual_seed(42) input_size, hidden_size, output_size = 10, 20, 5 learner = ProgressiveLearner(input_size, hidden_size, output_size) # 模拟多个连续任务 for task in range(3): print(f"\nTraining on Task {task + 1}") X = torch.randn(100, input_size) y = torch.randn(100, output_size) learner.train_task(X, y, epochs=50) # 测试在各个任务上的表现 X_test = torch.randn(10, input_size) for task in range(3): y_pred = learner.predict(X_test, task) print(f"\nPredictions for Task {task + 1}:") print(y_pred)
这些示例展示了终身学习系统设计的几个关键方面。在实际应用中,这些方法通常需要更复杂和大规模的实现:
此外,在设计终身学习系统时,还需要考虑:
通过综合运用这些技术和策略,我们可以开发出更加智能和适应性强的 AI 系统,能够在不断变化的环境中持续学习和改进。这对于创建真正的通用人工智能至关重要,使 AI 能够像人类一样,在整个"生命周期"中不断学习和成长。