赞
踩
感知器在历史上是非常松散地模仿生物神经元的。就像生物神经元一样,有输入和输出,“信号”从输入流向输出,如图所示。
1.输入权重(Input Weights):每个输入都有一个相对应的权重,用来调节输入对神经元的影响程度。
2.加权和(Weighted Sum):将每个输入乘以相应的权重,然后将它们加总起来。
3.激活函数(Activation Function):通常是阈值函数,比如单位阶跃函数(Step Function),用来确定神经元是否应该激活(输出1)或不激活(输出0)。
1.对于给定的输入向量 (\mathbf{x} = (x1, x2, \ldots, xn)),感知器计算加权和:[ z = \sum{i=1}^{n} wi \cdot xi + b ]
其中,( wi ) 是输入 ( xi ) 对应的权重,( b ) 是偏置(bias)。
2.然后,通过激活函数 ( \phi(z) ) 处理加权和 ( z ),产生神经元的输出 ( \hat{y} ):
[ \hat{y} = \phi(z) ]
其中,通常使用的阈值函数为:
[ \phi(z) =
1.初始化权重和偏置。
2.对每个训练样本 ( (\mathbf{x}, y) ) 执行以下步骤:
计算感知器的预测输出 ( \hat{y} )。
根据预测结果和实际标签 ( y ),调整权重和偏置:
[ wi \leftarrow wi + \alpha \cdot (y - \hat{y}) \cdot x_i ]
[ b \leftarrow b + \alpha \cdot (y - \hat{y}) ]
其中,( \alpha ) 是学习率。
Sigmoid函数是一个常用的激活函数,其数学表达式为:
[ \sigma(z) = \frac{1}{1 + e^{-z}} ]
特点:
1.输出范围在(0, 1)之间,即 ( \sigma(z) \in (0, 1) ),可以看作是将输入转换为概率的函数。
2.平滑连续,输出非常适合用于表示概率。
3.容易求导,导数形式简单 ( \sigma'(z) = \sigma(z) \cdot (1 - \sigma(z)) ),有利于梯度下降算法的优化。
适用场景:
1.输出是概率值的二分类问题。
2.隐藏层中的非线性转换,但是由于其存在梯度饱和问题(在极端值附近梯度接近于0),在深度网络中使用时可能导致梯度消失问题。
Tanh函数是双曲正切函数,其数学表达式为:
[ \tanh(z) = \frac{e^z - e^{-z}}{e^z + e^{-z}} ]
特点:
1.输出范围在(-1, 1)之间,即 ( \tanh(z) \in (-1, 1) ),使得其均值为0,有助于神经网络的收敛速度。
2.与Sigmoid函数类似,也是平滑连续的。
3.对输入的响应更强,相对于Sigmoid函数,它的梯度变化更大。
适用场景:
1.隐藏层中的非线性转换,可以用来处理输入均值为0的情况。
2.在输出层需要的值在[-1, 1]之间的情况。
ReLU(Rectified Linear Unit)函数是一种简单而广泛使用的激活函数,其数学表达式为:
[ \text{ReLU}(z) = \max(0, z) ]
特点:
1.非常简单和高效,计算速度快。
2.解决了Sigmoid和Tanh函数的梯度消失问题。
3.对于正值区域,梯度恒定为1,有利于梯度传播,加速收敛。
适用场景:
1.在深度神经网络中广泛应用,特别是在隐藏层。
2.适用于稀疏数据和计算资源有限的情况。
Softmax函数通常用于多分类问题的输出层,其数学表达式为:
[ \text{Softmax}(\mathbf{z})i = \frac{e^{zi}}{\sum{j=1}^{K} e^{zj}} \quad \text{for } i = 1, \ldots, K ]
特点:
1.将向量转换为概率分布,输出层的所有值都在(0, 1)之间,且总和为1。
2.适用于多类别分类问题,可以表示每个类别的概率。
适用场景:
输出层需要将神经网络的原始输出转换为概率分布,例如图像分类、语言模型等多分类问题。
总结
每种激活函数都有其独特的数学性质和适用场景。选择合适的激活函数取决于你的问题的性质以及神经网络的结构和需求。ReLU是目前在隐藏层中最常用的激活函数,而在输出层,通常使用Sigmoid或Softmax来得到适合的输出形式。
均方误差(Mean Squared Error, MSE)损失函数用于回归问题,它计算预测值与实际值之间的平方误差的平均值。数学表达式如下:
[ \text{MSE} = \frac{1}{n} \sum{i=1}^{n} (yi - \hat{y}i)^2 ]
其中,( yi ) 是真实的目标值,( \hat{y}_i ) 是模型预测的值,( n ) 是样本数量。
特点:
1.对异常值(outliers)比较敏感,因为误差项被平方。
2.适合于回归问题,如房价预测、连续值预测等。
3.梯度计算简单,便于优化算法的收敛。
分类交叉熵损失函数用于多分类问题,特别是对输出进行one-hot编码的情况。它衡量两个概率分布之间的距离,即模型输出的概率分布与实际标签的分布之间的差异。数学表达式如下:
[ \text{Categorical Cross-Entropy Loss} = -\sum{i} yi \log(\hat{y}i) ]
其中,( yi ) 是真实的标签(one-hot编码形式),( \hat{y}_i ) 是模型预测的概率分布,( \log ) 是自然对数。
特点:
1.适合多类别分类问题。
2.相比于其他损失函数(如均方误差),对于概率分布的变化更敏感,因为它比较的是整体分布而不是单个值。
3.梯度计算相对简单,是神经网络中常用的损失函数之一。
二元交叉熵损失函数通常用于二分类问题,其中输出为一个二元标签(0或1)。它也是比较两个概率分布的差异,但适用于仅有两个可能类别的情况。数学表达式如下:
[ \text{Binary Cross-Entropy Loss} = - \left( y \log(\hat{y}) + (1 - y) \log(1 - \hat{y}) \right) ]
其中,( y ) 是真实的标签(0或1),( \hat{y} ) 是模型预测的概率值(通常是一个sigmoid函数的输出)。
特点:
1.适合于二分类问题。
2.相较于多类别情况,计算简单,但在处理多类别时需要进行适当的调整。
3.对于输出为概率的任务效果较好,能够直接优化预测值和目标值之间的对数损失。
总结
选择适当的损失函数取决于你的问题类型和输出的性质。均方误差适用于回归问题,而分类交叉熵和二元交叉熵适用于分类问题,具体选择要根据问题的特点和数据的分布来决定。
1.选择模型:
在机器学习中,选择合适的模型意味着根据问题的特性和数据的特点来确定最适合的算法或模型类型。这决定了我们如何处理数据以及如何进行预测或分类。
2.整合:基于梯度的监督学习:
基于梯度的监督学习是指使用梯度下降等优化算法来训练模型,以最小化损失函数并使模型能够对新数据做出准确预测。这是大多数深度学习和传统机器学习方法的基础。
3.辅助训练概念:
辅助训练概念包括批量大小、学习率调整、批量归一化等技术,它们帮助加快训练速度、提高模型收敛速度或改进模型性能。
4.正确衡量模型性能:评估指标
评估指标用于量化模型在训练数据上的表现,例如分类准确率、均方误差(MSE)等。选择适当的评估指标取决于问题的性质和所需的预测精度。
5.正确衡量模型性能:数据集划分
将数据集划分为训练集、验证集和测试集是为了评估模型的泛化能力。训练集用于训练模型,验证集用于调整超参数,测试集用于最终评估模型性能。
6.知道何时停止训练:
在训练模型时,需要了解何时停止训练,以避免模型在训练数据上过拟合。这可以通过监控验证集上的性能来实现,一旦性能不再改善,就可以停止训练。
7.找到合适的超参数:
超参数是模型训练过程中需要手动设置的参数,如学习率、正则化项系数等。通过调整这些超参数可以优化模型的性能和泛化能力。
8.正则化:
正则化是一种控制模型复杂度的技术,有助于防止过拟合。常见的正则化方法包括L1正则化和L2正则化,它们通过向损失函数中添加惩罚项来实现。
首先,我们需要理解Yelp评论数据集的结构和内容。通常,Yelp评论数据集包含了用户对商家的评论文本以及相应的星级评分。我们需要准备数据集,并创建用于加载和处理数据的类。
在PyTorch中,数据集通常通过继承 torch.utils.data.Dataset 类来表示。这个类需要实现 __len__ 方法(返回数据集的大小)和 __getitem__ 方法(返回一个样本)。
- import torch
- from torch.utils.data import Dataset
-
- class YelpDataset(Dataset):
- def __init__(self, data, tokenizer, max_length):
- self.data = data
- self.tokenizer = tokenizer
- self.max_length = max_length
-
- def __len__(self):
- return len(self.data)
-
- def __getitem__(self, idx):
- review_text = self.data[idx]['review'] # 假设数据中有 'review' 字段
- rating = self.data[idx]['rating'] # 假设数据中有 'rating' 字段
-
- # 使用分词器对评论文本进行处理
- tokens = self.tokenizer(review_text, max_length=self.max_length, truncation=True, padding='max_length')
-
- input_ids = torch.tensor(tokens['input_ids'])
- attention_mask = torch.tensor(tokens['attention_mask'])
- label = torch.tensor(rating)
-
- return input_ids, attention_mask, label
- torch.utils.data.DataLoader 来加载数据并生成批次。
- from transformers import BertTokenizer
- from torch.utils.data import DataLoader
-
- # 初始化分词器
- tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
-
- # 准备数据集
- train_data = [...] # 假设已经加载和处理了训练数据
- valid_data = [...] # 假设已经加载和处理了验证数据
-
- # 创建数据集实例
- train_dataset = YelpDataset(train_data, tokenizer, max_length=128)
- valid_dataset = YelpDataset(valid_data, tokenizer, max_length=128)
-
- # 创建数据加载器
- train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)
- valid_loader = DataLoader(valid_dataset, batch_size=16)
- torch.utils.data.DataLoader 来加载数据并生成批次。
- from transformers import BertTokenizer
- from torch.utils.data import DataLoader
-
- # 初始化分词器
- tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
-
- # 准备数据集
- train_data = [...] # 假设已经加载和处理了训练数据
- valid_data = [...] # 假设已经加载和处理了验证数据
-
- # 创建数据集实例
- train_dataset = YelpDataset(train_data, tokenizer, max_length=128)
- valid_dataset = YelpDataset(valid_data, tokenizer, max_length=128)
-
- # 创建数据加载器
- train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)
- valid_loader = DataLoader(valid_dataset, batch_size=16)
- import torch.optim as optim
-
- def train(model, train_loader, optimizer, criterion, epochs=10):
- model.train()
- for epoch in range(epochs):
- running_loss = 0.0
- for input_ids, attention_mask, labels in train_loader:
- optimizer.zero_grad()
-
- # 将输入数据传入模型
- outputs = model(input_ids)
-
- # 计算损失
- loss = criterion(outputs, labels.float().view(-1, 1))
-
- # 反向传播和优化
- loss.backward()
- optimizer.step()
-
- running_loss += loss.item()
-
- print(f"Epoch {epoch+1}/{epochs}, Loss: {running_loss / len(train_loader)}")
-
- # 初始化模型和优化器
- model = PerceptronClassifier(input_dim=128) # 假设输入维度为BERT模型的输出大小
- optimizer = optim.Adam(model.parameters(), lr=0.001)
- criterion = nn.BCEWithLogitsLoss()
-
- # 开始训练
- train(model, train_loader, optimizer, criterion)
- def evaluate(model, data_loader):
- model.eval()
- correct = 0
- total = 0
- with torch.no_grad():
- for input_ids, attention_mask, labels in data_loader:
- outputs = model(input_ids)
- predicted = (torch.sigmoid(outputs) > 0.5).float()
-
- total += labels.size(0)
- correct += (predicted == labels.float().view_as(predicted)).sum().item()
-
- accuracy = correct / total
- print(f"Accuracy: {accuracy}")
-
- # 在验证集上评估模型
- evaluate(model, valid_loader)
-
- # 进行推断
- def predict_sentiment(model, tokenizer, review_text):
- model.eval()
- tokens = tokenizer(review_text, max_length=128, truncation=True, padding='max_length', return_tensors='pt')
- input_ids = tokens['input_ids']
- with torch.no_grad():
- outputs = model(input_ids)
- predicted = torch.sigmoid(outputs) > 0.5
-
- sentiment = "positive" if predicted.item() == 1 else "negative"
- return sentiment
-
- # 示例推断
- review = "This restaurant is great!"
- sentiment = predict_sentiment(model, tokenizer, review)
- print(f"Predicted sentiment: {sentiment}")
多层感知器(MLP)是一种基本的前馈神经网络模型,由多个全连接层(或称为密集层)组成,每个层之间的神经元完全连接。它是一种广泛用于分类和回归任务的模型。
输入层:接收输入特征。
隐藏层:由多个全连接层组成,每一层通过激活函数引入非线性。
输出层:产生模型的输出,可以是分类标签的概率分布或者回归值。
前向传播:输入数据通过每一层的权重矩阵和偏置向量,经过激活函数得到每一层的输出,最终得到模型的预测输出。
反向传播:使用损失函数衡量预测输出与真实标签之间的差距,通过反向传播算法调整每一层的权重和偏置,以减小损失函数,提高模型的预测能力。
数据准备
-
- surnames = ['Smith', 'Johnson', 'Williams', 'Jones', 'Brown', 'Davis']
- labels = [0, 1, 0, 1, 0, 1] # 假设0和1代表两个不同的类别
数据预处理
- import numpy as np
- import torch
-
- # 构建字符级别的特征表示
- char_to_index = {char: idx for idx, char in enumerate(set(''.join(surnames)))}
- num_chars = len(char_to_index)
-
- def surname_to_features(surname):
- features = np.zeros(num_chars)
- for char in surname:
- features[char_to_index[char]] = 1
- return features
-
- # 将数据转换为特征张量和标签张量
- surname_features = [surname_to_features(surname) for surname in surnames]
- surname_features = torch.tensor(surname_features, dtype=torch.float32)
- labels = torch.tensor(labels, dtype=torch.long)
模型定义
- import torch.nn as nn
-
- class MLP(nn.Module):
- def __init__(self, input_size, hidden_size, num_classes):
- super(MLP, self).__init__()
- self.fc1 = nn.Linear(input_size, hidden_size)
- self.relu = nn.ReLU()
- self.fc2 = nn.Linear(hidden_size, num_classes)
-
- def forward(self, x):
- out = self.fc1(x)
- out = self.relu(out)
- out = self.fc2(out)
- return out
-
- # 初始化模型
- input_size = num_chars
- hidden_size = 16
- num_classes = 2 # 两个类别
- model = MLP(input_size, hidden_size, num_classes)
训练和评估
- import torch.optim as optim
-
- criterion = nn.CrossEntropyLoss()
- optimizer = optim.Adam(model.parameters(), lr=0.001)
-
- # 训练模型
- num_epochs = 100
- for epoch in range(num_epochs):
- optimizer.zero_grad()
- outputs = model(surname_features)
- loss = criterion(outputs, labels)
- loss.backward()
- optimizer.step()
-
- if (epoch+1) % 10 == 0:
- print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')
-
- # 在训练结束后进行预测
- with torch.no_grad():
- predicted = model(surname_features)
- _, predicted_labels = torch.max(predicted, 1)
- print('Predicted labels:', predicted_labels.numpy())
总结
多层感知器通过多个全连接层和非线性激活函数,能够很好地学习输入数据的复杂特征,并在分类任务中表现出色。在姓氏分类的示例中,它可以有效地区分不同类别的姓氏,展示了其在简单到中等复杂度分类任务中的应用潜力。
卷积(Convolution)在深度学习中是一种重要的操作,特别是在处理图像和序列数据时具有显著的优势。卷积神经网络(Convolutional Neural Network,CNN)利用了卷积操作的特性,广泛应用于图像识别、语音识别、自然语言处理等领域。
卷积操作是信号处理中的一种重要数学工具,它在深度学习中被引入以处理多维数据,例如图像。其核心思想是通过滑动一个卷积核(也称为滤波器)在输入数据上进行局部区域的乘加运算,从而提取特征。
具体来说,对于二维输入数据(如图像),卷积操作可以描述为:
[ (f * g)(x, y) = \sum{i=0}^{m-1} \sum{j=0}^{n-1} f(x-i, y-j) \cdot g(i, j) ]
其中,( f ) 是输入数据,( g ) 是卷积核(滤波器),( (x, y) ) 是输出特征图中的位置。卷积操作通过在输入数据上滑动卷积核并执行乘加运算来计算输出特征图中每个位置的值。
数据准备与预处理
- import torch
- import torch.nn as nn
- import torch.optim as optim
- import numpy as np
-
- # 假设有如下数据集和标签
- surnames = ['Smith', 'Johnson', 'Williams', 'Jones', 'Brown', 'Davis']
- labels = [0, 1, 0, 1, 0, 1] # 0和1代表两个不同的类别
-
- # 字符级别的one-hot编码
- char_to_index = {char: idx for idx, char in enumerate(set(''.join(surnames)))}
- num_chars = len(char_to_index)
-
- def surname_to_features(surname):
- features = np.zeros(num_chars)
- for char in surname:
- features[char_to_index[char]] = 1
- return features
-
- surname_features = [surname_to_features(surname) for surname in surnames]
- surname_features = torch.tensor(surname_features, dtype=torch.float32)
- labels = torch.tensor(labels, dtype=torch.long)
定义卷积神经网络模型
- class CNN(nn.Module):
- def __init__(self, input_size, num_classes):
- super(CNN, self).__init__()
- self.conv1 = nn.Conv1d(in_channels=input_size, out_channels=16, kernel_size=3, padding=1)
- self.relu = nn.ReLU()
- self.pool = nn.MaxPool1d(kernel_size=2)
- self.fc = nn.Linear(16 * 2, num_classes) # 16是卷积核的输出通道数,2是池化后的长度
-
- def forward(self, x):
- x = x.unsqueeze(1) # 在第二个维度上添加通道维度
- x = self.conv1(x)
- x = self.relu(x)
- x = self.pool(x)
- x = x.view(x.size(0), -1) # 展平为向量
- x = self.fc(x)
- return x
-
- # 初始化模型
- input_size = num_chars
- num_classes = 2 # 两个类别
- model = CNN(input_size, num_classes)
训练和评估
- criterion = nn.CrossEntropyLoss()
- optimizer = optim.Adam(model.parameters(), lr=0.001)
-
- # 训练模型
- num_epochs = 100
- for epoch in range(num_epochs):
- optimizer.zero_grad()
- outputs = model(surname_features)
- loss = criterion(outputs, labels)
- loss.backward()
- optimizer.step()
-
- if (epoch+1) % 10 == 0:
- print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')
-
- # 在训练结束后进行预测
- with torch.no_grad():
- predicted = model(surname_features)
- _, predicted_labels = torch.max(predicted, 1)
- print('Predicted labels:', predicted_labels.numpy())
总结
卷积神经网络通过卷积操作和池化操作能够有效地从输入数据中提取特征,特别适用于处理像图像和序列这样的结构化数据。在姓氏分类任务中,CNN能够学习和区分不同姓氏之间的模式,从而进行准确的分类预测。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。