一 模型定义
感知机模型是一个二分类线性分类模型,输入为实例的特征向量,输出为实例的类别,取值为-1,+1。感知机对应的是将输入空间中将实例划分为正,负两类的超平面。
感知机模型对应函数f(x) = sign(w*x 十 b)
其中, ω 和 b 为感知机模型参数, ω 叫作权值 , b 叫作偏置(w,b都是以向量的形式存在), sign 是符号函数。
符号函数图像
二 模型损失函数
感知机学习的目标是求得一个能够将训练集正实例点和负实例点完全正确分开的分离超平面。感知机模型的学习指的是对参数 w和b的学习。
感知机模型的学习策略是定义一个损失函数并使损失函数最小化。
感知机模型的损失函数基于所有误分类点(一个实例本来是正(负)实例而感知机模型将该实例错误的分为负(正)实例)到分离超平面的距离之和,当没有误分类点时损失函数为0,误分类点离分离超平面越近,损失函数越小,感知机模型分类正确性也越高
输入空间中任一点X0到分离超平面的距离是其中 ||ω|| 是 ω 的 L2 范数(L2范数是指向量各元素的平方和然后求平方根)
对于每一个误分类点(xi,yi)来说,
假设超平面 S 的误分类点集合为 M, 那么所有误分类点到超平面 S 的总 距离为
不考虑 1/||w||,就得到感知机学习的损失函数
三 模型学习算法
感知机模型学习算法的目的是求出参数w,b ,使其可以最小化感知机损失函数
其中 M 为误分类点的集合。
感知机算法以误分类驱动,具体采用随机梯度下降算法
在最初时为w,b随机赋值为 w0,b0,然后用梯度下降法不断极小化感知机损失函数。有个注意点是,在极小化过程中不是一次使M中所有误分类点的梯度下降,而是一次随机选取一个误分类点使其梯度下降。
其中 η是学习率,通过迭代可以使损失函数不断减小
感知机算法训练过程
输入:训练集以及学习率 η
输出: 模型参数w,b
(1)选取初值w0, b0
(2) 在训练集中选取数据 (xi, yi)
(3) 如果 yi(ω • xi + b) <=0,
ω ← ω+ηyixi
b ← b+ η*yi
(4) 转至 (2),直至训练集中没有误分类点。
四 代码实现
数据来源于和鲸社区
因为数据中大多数特征值是离散的 并且是以自然语言的形式呈现的 比如
OnlineSecurity有三种取值No,Yes,No internet service,可以用LabelEncoder来编码 结果是以数字0,1,2分别代表这三种类型 对所有值是离散类型的特征都采用这种方法来处理
def datapreprocessing(data):#数据预处理
le = LabelEncoder()
data['gender'] = le.fit_transform(data['gender'].values)
data['Partner'] = le.fit_transform(data['Partner'].values)
data['Dependents'] = le.fit_transform(data['Dependents'].values)
data['PhoneService'] = le.fit_transform(data['PhoneService'].values)
data['MultipleLines'] = le.fit_transform(data['MultipleLines'].values)
data['InternetService'] = le.fit_transform(data['InternetService'].values)
data['OnlineSecurity'] = le.fit_transform(data['OnlineSecurity'].values)
data['OnlineBackup'] = le.fit_transform(data['OnlineBackup'].values)
data['DeviceProtection'] = le.fit_transform(data['DeviceProtection'].values)
data['TechSupport'] = le.fit_transform(data['TechSupport'].values)
data['StreamingTV'] = le.fit_transform(data['StreamingTV'].values)
data['StreamingMovies'] = le.fit_transform(data['StreamingMovies'].values)
data['Contract'] = le.fit_transform(data['Contract'].values)
data['PaperlessBilling'] = le.fit_transform(data['PaperlessBilling'].values)
data['PaymentMethod'] = le.fit_transform(data['PaymentMethod'].values)
data['Churn'] = le.fit_transform(data['Churn'].values)
print(data)
data.to_csv('Customer-Churn.csv')#
TotalCharges这一列有空白值 首先用0填充缺失值,以把这一列的数据类型由字符串转换为浮点型 之后求出这一列的平均值来取代为0的值
df=read_data("Customer-Churn.csv")#读数据
df['TotalCharges'] = df['TotalCharges'].replace(" ", "0")#TotalCharges中有空格
df['TotalCharges'] = pd.to_numeric(df['TotalCharges'])
TotalCharges = []
for i in range(df.shape[0]):
TotalCharges.append(float(df.loc[i, 'TotalCharges'])) # 将字符串数据转化为浮点型加入到数组之中
avg=np.var(TotalCharges)
df['TotalCharges'] = df['TotalCharges'].replace(0, avg)#用均值填充缺失值
划分特征和标签 并对数据进行标准化处理
def prepare_data(df):#数据预处理
ndarray_data = df.values
X=df.iloc[:,2:21]#数据切片
Y=df.iloc[:,21]
print(X)
#特征值标准化\n"
minmax_scale = preprocessing.MinMaxScaler(feature_range=(0, 1))
X = minmax_scale.fit_transform(X)
Y = Y.replace(0, -1)
return X , Y
感知机模型
class Model:#感知机模型
def __init__(self,data):
self.w = np.zeros(df.columns.size-3, dtype=np.float32)
self.b=0
self.a=0.1#学习率
def sign(self, x, w, b):
y=np.dot(w,x)+b
return y
def fit(self, X_train, Y_train):
isfinish=False
while isfinish==False:
isfinish = True
for i in range(X_train.shape[0]):
X=X_train[i]
Y=Y_train[i]
y=self.sign(X, self.w, self.b)
if Y*y <=0:#如果该点是误分类点
self.w=self.w+self.a * np.dot(Y,X)
self.b=self.b+ self.a*Y
isfinish = False
return self.w,self.b #返回训练好的模型的参数