一、逻辑门多层感知机实现
第1关:使用感知机实现与、或、与非逻辑门
import numpy as np
def mlp_and(x1, x2):
w1, w2, theta = 0.5, 0.5, 0.7
activation = x1 * w1 + x2 * w2
return 1 if activation >= theta else 0
def mlp_or(x1, x2):
w1, w2, theta = 0.5, 0.5, 0.2
activation = x1 * w1 + x2 * w2
return 1 if activation >= theta else 0
def mlp_nand(x1, x2):
w1, w2, theta = -0.5, -0.5, -0.7
activation = x1 * w1 + x2 * w2
return 1 if activation >= theta else 0
2.使用多层感知机实现异或逻辑门
import numpy as np
def mlp_and(x1, x2):
x = np.array([x1, x2]).astype(np.float32)
weight = np.array([0.5, 0.5]).astype(np.float32)
bias = -0.7
y = np.dot(weight, x) + bias
if y <= 0:
return 0
else:
return 1
def mlp_or(x1, x2):
x = np.array([x1, x2]).astype(np.float32)
weight = np.array([0.5, 0.5]).astype(np.float32)
bias = -0.2
y = np.dot(weight, x) + bias
if y <= 0:
return 0
else:
return 1
def mlp_nand(x1, x2):
x = np.array([x1, x2]).astype(np.float32)
weight = np.array([-0.5, -0.5]).astype(np.float32)
bias = 0.7
y = np.dot(weight, x) + bias
if y <= 0:
return 0
else:
return 1
def mlp_xor(x1, x2):
# 使用mlp_nand实现NOT操作
not_x1 = mlp_nand(x1, x1)
not_x2 = mlp_nand(x2, x2)
# 使用mlp_and实现AND操作
and1 = mlp_and(x1, not_x2)
and2 = mlp_and(not_x1, x2)
# 使用mlp_or实现OR操作
y = mlp_or(and1, and2)
return y
二、感知机
1.感知机 - 西瓜好坏自动识别
#encoding=utf8
import numpy as np
# 构建感知机算法
class Perceptron(object):
def __init__(self, learning_rate = 0.01, max_iter = 200):
self.lr = learning_rate
self.max_iter = max_iter
def fit(self, data, label):
'''
input:data(ndarray):训练数据特征
label(ndarray):训练数据标签
output:w(ndarray):训练好的权重
b(ndarray):训练好的偏置
'''
# 初始化权重和偏置
self.w = np.array([1.] * data.shape[1])
self.b = np.array([1.])
# 开始训练
for _ in range(self.max_iter):
has_wrong = False
for idx in range(len(data)):
x = data[idx]
y = label[idx]
# 如果当前数据点被错误分类
if y * (np.dot(self.w, x) + self.b) <= 0:
has_wrong = True
# 更新权重和偏置
self.w += self.lr * y * x
self.b += self.lr * y
# 如果没有错误分类的数据点,结束训练
if not has_wrong:
return None
return None
def predict(self, data):
'''
input:data(ndarray):测试数据特征
output:predict(ndarray):预测标签
'''
predict = []
for i in range(data.shape[0]):
# 计算预测结果
result = np.dot(self.w, data[i]) + self.b
# 根据结果的正负确定标签
if result >= 0:
result = 1
else:
result = -1
predict.append(result)
# 将预测结果转换为numpy数组
predict = np.array(predict)
return predict
2.scikit-learn感知机实践 - 癌细胞精准识别
#encoding=utf8
import os
import pandas as pd
from sklearn.linear_model import Perceptron
# 检查并删除已存在的result.csv文件
if os.path.exists('./step2/result.csv'):
os.remove('./step2/result.csv')
# 获取训练数据
train_data = pd.read_csv('./step2/train_data.csv')
# 获取训练标签
train_label = pd.read_csv('./step2/train_label.csv')
train_label = train_label['target']
# 获取测试数据
test_data = pd.read_csv('./step2/test_data.csv')
# 创建Perceptron分类器实例
clf = Perceptron(max_iter=1000, eta0=0.1, random_state=666)
# 训练模型
clf.fit(train_data, train_label)
# 获取预测标签
predict = clf.predict(test_data)
# 将预测标签写入csv
df = pd.DataFrame({'result': predict})
df.to_csv('./step2/result.csv', index=False)
三、感知算法的实现
1.感知机的算法
import warnings
warnings.filterwarnings("ignore")
import numpy as np
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import Perceptron
def main():
data_path = '/data/workspace/myshixun/SMSSpamCollection'
df = pd.read_csv(data_path, delimiter='\t', header=None)
# 将label编码,'spam'为0, 'ham'为1
df[0] = df[0].replace(to_replace=['spam', 'ham'], value=[0, 1])
# 完成数据划分及词向量的转化
X = df[1].values # 文本数据
y = df[0].values # 标签数据
# 划分训练集和测试集
X_train_raw, X_test_raw, y_train, y_test = train_test_split(X, y, random_state=2)
# 创建TF-IDF向量化器实例
vectorizer = TfidfVectorizer()
# 将训练数据向量化
x_train = vectorizer.fit_transform(X_train_raw)
# 将测试数据向量化
x_test = vectorizer.transform(X_test_raw)
# 构建Perceptron模型
model = Perceptron()
# 训练模型
model.fit(x_train, y_train)
# 对测试集进行预测
x_pre_test = model.predict(x_test)
# 计算验证集的准确度
acc = model.score(x_test, y_test)
return acc
四、多层感知机的实现
1.实现全连接层的前向传播
import numpy as np
class FullyConnected:
def __init__(self, W, b):
r'''
全连接层的初始化。
Parameter:
- W: numpy.array, (D_in, D_out)
- b: numpy.array, (D_out)
'''
self.W = W
self.b = b
self.x = None
self.original_x_shape = None
def forward(self, x):
r'''
全连接层的前向传播。
Parameter:
- x: numpy.array, (B, d1, d2, ..., dk)
Return:
- y: numpy.array, (B, M)
'''
# 保存输入数据的形状和大小
self.original_x_shape = x.shape
x = x.reshape(x.shape[0], -1) # 将输入展平为一维向量
# 执行矩阵乘法并添加偏置
y = np.dot(x, self.W) + self.b
return y
# 初始化全连接层
W = np.array([[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]])
b = np.array([0.1, 0.2, 0.3])
x = np.array([[1, 2], [3, 4]])
2.实现常见激活函数的前向传播
import numpy as np
class Sigmoid:
def __init__(self):
self.out = None
def forward(self, x):
r'''
Sigmoid激活函数的前向传播。
Parameter:
- x: numpy.array, (B, d1, d2, ..., dk)
Return:
- y: numpy.array, (B, d1, d2, ..., dk)
'''
self.out = 1 / (1 + np.exp(-x))
return self.out
class ReLU:
def __init__(self):
self.mask = None
def forward(self, x):
r'''
ReLU激活函数的前向传播。
Parameter:
- x: numpy.array, (B, d1, d2, ..., dk)
Return:
- y: numpy.array, (B, d1, d2, ..., dk)
'''
self.mask = (x > 0)
return x * self.mask
# 测试sigmoid和ReLU激活函数
sigmoid = Sigmoid()
relu = ReLU()
x_sigmoid = np.array([[-1, 0, 1]])
x_relu = np.array([[-1, 0, 1]])
output_sigmoid = sigmoid.forward(x_sigmoid)
output_relu = relu.forward(x_relu)