04 Jan 2020
预备知识:
1.手工计算一个神经网络
2.Python手工编写神经网络算法
实验数据:
训练集mnist_train_100
测试集mnist_test_10
· 手工编写一个神经网络
import numpy
# scipy.special for the sigmoid function expit()
import scipy.special
# library for plotting arrays
import matplotlib.pyplot
# ensure the plots are inside this notebook, not an external window
%matplotlib inline
# neural network class definition
class neuralNetwork:
# initialise the neural network
def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
# set number of nodes in each input, hidden, output layer
self.inodes = inputnodes
self.hnodes = hiddennodes
self.onodes = outputnodes
# link weight matrices, wih and who
# weights inside the arrays are w_i_j, where link is from node i to node j in the next layer
# w11 w21
# w12 w22 etc
self.wih = numpy.random.normal(0.0, pow(self.inodes, -0.5), (self.hnodes, self.inodes))
self.who = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.onodes, self.hnodes))
# learning rate
self.lr = learningrate
# activation function is the sigmoid function
self.activation_function = lambda x: scipy.special.expit(x)
pass
# train the neural network
def train(self, inputs_list, targets_list):
# convert inputs list to 2d array
inputs = numpy.array(inputs_list, ndmin=2).T
targets = numpy.array(targets_list, ndmin=2).T
# calculate signals into hidden layer
hidden_inputs = numpy.dot(self.wih, inputs)
# calculate the signals emerging from hidden layer
hidden_outputs = self.activation_function(hidden_inputs)
# calculate signals into final output layer
final_inputs = numpy.dot(self.who, hidden_outputs)
# calculate the signals emerging from final output layer
final_outputs = self.activation_function(final_inputs)
# output layer error is the (target - actual)
output_errors = targets - final_outputs
# hidden layer error is the output_errors, split by weights, recombined at hidden nodes
hidden_errors = numpy.dot(self.who.T, output_errors)
# update the weights for the links between the hidden and output layers
self.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)), numpy.transpose(hidden_outputs))
# update the weights for the links between the input and hidden layers
self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))
pass
# query the neural network
def query(self, inputs_list):
# convert inputs list to 2d array
inputs = numpy.array(inputs_list, ndmin=2).T
# calculate signals into hidden layer
hidden_inputs = numpy.dot(self.wih, inputs)
# calculate the signals emerging from hidden layer
hidden_outputs = self.activation_function(hidden_inputs)
# calculate signals into final output layer
final_inputs = numpy.dot(self.who, hidden_outputs)
# calculate the signals emerging from final output layer
final_outputs = self.activation_function(final_inputs)
return final_outputs
· 训练这个神经网络
# number of input, hidden and output nodes
input_nodes = 784
hidden_nodes = 200
output_nodes = 10
# learning rate
learning_rate = 0.1
# create instance of neural network
n = neuralNetwork(input_nodes,hidden_nodes,output_nodes, learning_rate)
# load the mnist training data CSV file into a list
training_data_file = open("d:/mnist_train_100.csv", 'r')
training_data_list = training_data_file.readlines()
training_data_file.close()
# train the neural network
# epochs is the number of times the training data set is used for training
epochs = 5
for e in range(epochs):
# go through all records in the training data set
for record in training_data_list:
# split the record by the ',' commas
all_values = record.split(',')
# scale and shift the inputs
inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01
# create the target output values (all 0.01, except the desired label which is 0.99)
targets = numpy.zeros(output_nodes) + 0.01
# all_values[0] is the target label for this record
targets[int(all_values[0])] = 0.99
n.train(inputs, targets)
pass
pass
测试这个神经网络
# load the mnist test data CSV file into a list
test_data_file = open("d:\\mnist_test_10.csv", 'r')
test_data_list = test_data_file.readlines()
test_data_file.close()
# test the neural network
# scorecard for how well the network performs, initially empty
scorecard = []
# go through all the records in the test data set
for record in test_data_list:
# split the record by the ',' commas
all_values = record.split(',')
# correct answer is first value
correct_label = int(all_values[0])
# scale and shift the inputs
inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01
# query the network
outputs = n.query(inputs)
# the index of the highest value corresponds to the label
label = numpy.argmax(outputs)
# append correct or incorrect to list
if (label == correct_label):
# network's answer matches correct answer, add 1 to scorecard
scorecard.append(1)
else:
# network's answer doesn't match correct answer, add 0 to scorecard
scorecard.append(0)
pass
pass
# calculate the performance score, the fraction of correct answers
scorecard_array = numpy.asarray(scorecard)
print ("performance = ", scorecard_array.sum() / scorecard_array.size)
all_values = test_data_list[0].split(",")
print(all_values[0])
n.query((numpy.asfarray(all_values[1:])/255.0*0.99) + 0.01)
## ====输出结果(第7行最大)====
array([[0.09974942],
[0.03166885],
[0.06538583],
[0.0988961 ],
[0.09711381],
[0.05002152],
[0.01467066],
[0.73531968],
[0.08138323],
[0.08918561]])
04 Jan 2020
之前写过手工计算一个神经网络,那么如何用python编写一个神经网络呢?接下来便试着一步步实现。神经网络一共分为三块,初始网络、训练网络、查询网络,由此所编写的代码框架如下:
# 神经网络框架
class neuralNetwork:
# 初始网络
def __int__():
pass
# 训练网络
def train():
pass
# 查询网络
def query():
pass
· 完整的神经网络代码
import scipy.special
import numpy
class neuralNetwork:
# 初始网络
def __init__(self,inputnodes,hiddennodes,outputnodes,learningrate):
# 设置输入、输出、隐藏层
self.inodes = inputnodes
self.hnodes = hiddennodes
self.onodes = outputnodes
# 设置权重
self.wih = numpy.random.normal(0.0, pow(self.hnodes, -0.5),(self.hnodes,self.inodes))
self.who = numpy.random.normal(0.0, pow(self.onodes, -0.5),(self.onodes,self.hnodes))
# 设置学习率
self.lr = learningrate
# 构建sigmiod函数
self.activation_function = lambda x: scipy.special.expit(x)
pass
# 训练网络
def train(self, inputs_list, targets_list):
# 第一层输入
inputs = numpy.array(inputs_list,ndmin=2).T
targets= numpy.array(targets_list,ndmin=2).T
# 隐藏层输入
# X隐含 = W权重 * I输入
hidden_inputs = numpy.dot(self.wih, inputs)
# 隐藏层输出
hidden_outputs = self.activation_function(hidden_inputs)
# 最终层输入
final_inputs = numpy.dot(self.wih, hidden_outputs)
# 最终层输出
final_outputs = self.activation_function(final_inputs)
# 误差值
output_errors = targets- final_outputs
# 反向传播 error隐藏 = WT隐藏 * error输出
hidden_errors = numpy.dot(self.who.T,output_errors)
# 传播隐藏到输出
self.who = self.who + self.lr* numpy.dot((output_errors*final_outputs*(1.0-final_outputs)),numpy.transpose(hidden_outputs))
# 传播输入到隐藏
self.wih = self.wih + self.lr* numpy.dot((output_errors*hidden_outputs*(1.0-hidden_outputs)),numpy.transpose(inputs))
pass
# 输出网络
def query(self, inputs_list):
# 第一层输入
inputs = numpy.array(inputs_list,ndmin=2).T
# 隐藏层输入
# X隐含 = W权重 * I输入
hidden_inputs = numpy.dot(self.wih, inputs)
# 隐藏层输出
hidden_outputs = self.activation_function(hidden_inputs)
# 最终层输入
final_inputs = numpy.dot(self.wih, hidden_outputs)
# 最终层输出
final_outputs = self.activation_function(final_inputs)
return final_outputs
· 训练这个神经网络,并输出相应结果
# 输入层、隐含层、输出层节点数
input_nodes =3
hidden_nodes =3
output_nodes =3
# 学习率
learningrate = 0.3
# 训练一个神经网络
n = neuralNetwork(input_nodes,hidden_nodes,output_nodes,learningrate)
# 查询网络
n.query([1,0.5,-1.5])
# ====最终输出结果(数值可能不相同)====
array([[0.40511455],
[0.40580834],
[0.50113563]])
26 Nov 2019
神经网络算法作为深度学习的基础,其重要性不言而喻。然而大部分同学,在实际学习过程中却总不得其门而入。某天受高人指点尝试去手工计算一个三层神经网络,于是一通百通,不仅了解了神经网络工作原理的本质、调优的方法,还用python自写了一套基础版的神经网络算法。本篇博文便一步步的将整个推导过程重现一遍。
1. 了解Sigmoid函数
Sigmoid函数(简称S函数) 对于大家来说并不陌生,其公式为:y = 1/1+E(-x)。当x趋近无穷大时,y趋近于1;当x趋近无穷小时,y趋近于0。因此S函数的输入x可以为任意数,而输出y必介于0到1之间。
那么S函数在神经网络中起什么作用呢,大家可以想象一下神经网络是由多个神经元共同作用而成,而神经元的工作方式是在接受输入到达一定量级的时候,才产生相应的输出。因此我们用S函数模拟神经元的工作方式,即当输入x到达一定界值时,S函数(神经元)就激发了。
我们举个例子计算一个神经元的输入及输出
例:假设x1=0.05,x2=0.25,x3=0.75求S函数的解
x = x1+x2+x3 = 0.05+0.25+0.75 = 1.05
y = 1/1+E(-x) = 1/1+E(-1.05) = 0.7488
2. 了解W权重
图1中可以看到,神经网络每个神经元之间都会有连接,而每个连接上都会有相应的权重W,那么神经网络前后层之间为什么要相互连接呢?第一,这种完全连接的方式可以相对容易编辑成计算机指令,第二,神经网络在迭代学习过程中自身会弱化不需要的链接,即权重趋近于0。在这里我们需要注意初始权重是随机值,神经网络需要做的就是不断调整权重以最大降低预测值与真实值之间的误差。加入权重后,单个神经元的计算方式如下图:
# 第2层第1个神经元输入x
x = (x1*w1,1)+(x2*w1,2)+(x3*w1,3) = 1*0.9+0.5*0.2+0.5*0.1 = 1.05
# 第2层第1个神经元输出y
y = 1/1+E(-x) = 1/1+E(-1.05) = 0.7488
3. 计算一个三层神经网络
这里我们先用最基础的方法去计算三层神经网络的输出结果,由于第三层(输出层)每个神经元的计算方式不尽相同,因此我们只计算第三层第一个神经元的输出,如下图:
这样我们就成功计算了一个三层神经网络的输出结果,是不是挺容易的?!
4. 借助矩阵计算神经网络
这里我们借助矩阵的方式去实现3中三层神经网络的计算,如下图:
这里我们极大的简化了神经网络的计算方式,并获得了相同的输出结果。后续用Python实现神经网络算法,
5. 如何计算反向传播误差
误差代表的是我们实际值与预测值之间的差异,即误差e=实际值t-预测值o。在误差反向传播的过程中,我们按照W权重来分配每个神经元的误差,如下图:
这里我们也可以借助矩阵来计算误差,图中e(hidden)=W(hidden_output)的转置矩阵*e(output)
6. 如何使用误差来调整权重
计算误差的目的,就是告诉神经网络如何去调整矩阵权重,以使得迭代计算出的预测值不断趋近于真实值。这里直接给出权重计算的公式,如下图:
这样我们整个神经网络的已经计算完成,最后强烈推荐一本书《Python神经网络编程》塔里克·拉希德著,接下来我们再试着用Python来实现一遍。
17 Oct 2018
协同过滤指的是关联推荐的一种思路,而不是指的某种特定的算法。它的思路非常简单,首先我将具有相同特征的客户放到一个类中,例如客户A与B相似,然后将客户A所购买过的产品直接推荐给客户B,反之亦然。
本文抛砖引玉,主要实现一个基于用户的协同过滤模型,若有兴趣的同学,后续可以从以下几个方面进行延伸:
1.如何用相同的方法实现基于产品的协同过滤模型;
2.如何利用其他相似度计算方法(余弦距离、聚类等)改进协同过滤模型;
协同过滤需要两份数据,包括用户特征信息表UserandFeature和用户产品关联表UserandLabel
· 基于用户协同过滤python程序
import csv
import math
import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler
# ==== 1.数据预处理 ====
data = pd.read_csv('d:\\UserandFeature.csv',sep=',',encoding='gbk')
# fillna()是pandas函数,用于数据填充(向前填充)
data = data.fillna(method = 'ffill', axis = 1).values
# MinMaxScaler最大最小标准化公式:X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
scaler = MinMaxScaler(feature_range=(0,1))
dataset = scaler.fit_transform(data)
# DataFrame是pandas表格框架,目的是为了打出UserandFeature表格
# dataset1 = pd.DataFrame(dataset)
# dataset1.to_csv('d:\\UserandFeature1.csv', mode='w', header=False)
# ==== 2.相似度计算 ====
def Pearson(vec1, vec2):
vec1_ = vec1 - np.mean(vec1)
vec2_ = vec2 - np.mean(vec2)
sum = np.dot(vec1_, vec2_) / (np.linalg.norm(vec1_) * np.linalg.norm(vec2_))
return sum
# dataset.shape[0]表示array的行数
for i in range(dataset.shape[0]):
vec1 = dataset[i-1]
corr=[]
for j in range(dataset.shape[0]):
vec2 = dataset[j-1]
corr.append(Pearson(vec1, vec2))
# 将结果打印到SimilarityofUsers表中
with open('d:\\SimilarityofUsers.csv','a',newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(corr)
# ==== 3.基于用户的推荐 ====
similarity = pd.read_csv('d:\\SimilarityofUsers.csv').values
# 导入用户产品关联列表,第一列表示用户,第二列表示产品(无表头)
label = pd.read_csv('d:\\UserandLabel.csv').values.tolist()
# 读取相似度列表
for m in range(similarity.shape[0]):
a=[m+1]
for n in range(similarity.shape[0]):
if similarity[m,n] > 0.85:
a.append(label[n-1])
else:
continue
# 将结果打印到recommend表中
with open('d:\\recommend.csv','a',newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(a)
24 May 2018
最近分析客户偏好的时候用到了因子分析,感觉是NLP与机器学习一个不错的结合点,遂在此记录一下。
因子分析的主要目的就是为了降维,意思是将多个字段的值按照不同的权重合为一个字段,其前提条件是需要合并的几个字段具有相关性,百度上有很多关于因子分析的计算公式,大家可以自行搜索一下,本文只给出因子分析的python计算程序。
这是借助因子分子做的客户偏好雷达图:
原始数据集下载地址:yinzifenxi.csv
· 因子分析python程序
import csv
import numpy as np
from sklearn.decomposition import FactorAnalysis
# ==== 读取原始数据集 ====
with open("d:\\yinzifenxi.csv","r") as f: # 读取原始CSV文件路径
data1 = np.loadtxt(f,delimiter=",",skiprows=1)
f = open("d:\\yinzifenxi.csv","r")
rows_dict = csv.DictReader(f)
# print(data1) # 打印原文件数据
# ==== 创建空白的CSV文件 ====
fieldnames = ['frequency','avg','coverage','yinzifenxi']
f1 = open("d:\\yinzifenxi1.csv","w",newline='') # 创建一个空白新的CSV文件
writer = csv.DictWriter(f1,fieldnames=fieldnames)
# ==== 因子分析 ====
data = np.array(data1[1:], dtype = np.float64) # 从第二行开始
fa = FactorAnalysis(n_components = 1) # 因子分析参数设置 1表示一维
fa.fit(data) # 因子分子数据输入
tran_data = fa.transform(data)
tran_data1=tran_data[:,0]
# print (tran_data1) # 打印因子分析结果
# ==== 将结果输入到CSV文件 ====
writer.writeheader()
for i,row in enumerate(rows_dict): # 将结果写入CSV
row['yinzifenxi'] = tran_data1[i-1]
writer.writerow(row)
· 因子分析结果
28 Apr 2018
最近在整理聚类算法的时候偶然发现一个指标——轮廓系数,仔细研究之后发现是一个易于理解的用来评估聚类效果好坏的指标,因此在这里和大家分享一样。轮廓系数的值介于[-1,1]之间,越趋于1代表聚类效果越好,具体计算方法如下:
1. 计算样本i到同簇其他所有样本的平均距离,记为a(i)。a(i)越接近0则表示样本i聚类效果越好。
2. 计算样本i到其他每个簇中所有样本的平均距离,选取平均距离最小的值记为b(i)。b(i)越大则表示样本i聚类效果越好。
3. 计算b(i)与a(i)的极差,除以max{a(i),b(i)},这时就会出现以下3种场景:
4. 判别结果:
若s(i)接近1,则说明样本i聚类合理;
若s(i)接近-1,则样本i更应该分类到另外的簇;
若s(i)接近0,则说明样本i在两个簇的边界上;
注意:轮廓系数相关程序已在Python之 文本聚类中给出,大家可自行研究。
23 Jan 2018
模型评估一直是数据建模中不可或缺的一环,评估指标的好坏直接关系到模型上线运用的情况。本文期望以最直观的方式告诉大家模型评估的相关指标,并手动绘制令诸多同学疑惑的ROC曲线。在此希望大家注意:模型评估指标只能作为参考依据,在真正的项目实施过程中,还是需要针对具体业务具体分析。
分类模型(贝叶斯、决策树、SVM等)评估指标:
评估指标
具体描述
sklearn对应函数
Precision
精准度
from sklearn.metrics import precision_score
Recall
召回率
from sklearn.metrics import recall_score
F1
F1值
from sklearn.metrics import f1_score
Confusion Matrix
混淆矩阵
from sklearn.metrics import confusion_matrix
ROC
ROC曲线
from sklearn.metrics import roc
AUC
ROC曲线下的面积
from sklearn.metrics import auc
回归模型(线性回归、非线性回归等)评估指标:
评估指标
具体描述
sklearn对应函数
Mean Square Error(MSE/RMSE)
平均方差
from sklearn.metrics import mean_squared_error
Absolute Error(MAE/RAE)
绝对误差
from sklearn.metrics import mean_absolute_error, median_absolute_error
R-Squared(R^2)
R平方值
from sklearn.metrics import r2_score
· 混淆矩阵、ROC曲线与AUC面积
问题1:混淆矩阵是什么?
回答1:混淆矩阵说简单一点就是预测的正例/反例与真实值之间的比例关系,该矩阵包括4个方面:
预测值
真实值
对应指标
正例
正例
True Positive(TP)
正例
反例
False Positive(FP)
反例
正例
True Negative(TN)
反例
反例
False Negative(FN)
混淆矩阵图如下:
由此计算:
True Positive Rate真实的正例中,被预测正确的比例:TPR = TP/(TP+FN)
False Positive Rate真实的反例中,被预测正确的比例:FPR = FP/(FP+TN)
问题2:混淆矩阵、ROC曲线与AUC面积之间的关系?
回答2:ROC曲线(Receiver Operating Characteristic)主要用于评估二分类模型的优劣,其绘图时X轴和Y轴分别对应混淆矩阵中FPR和TPR,其下方包围的面积为AUC(Area Under the Curve)。
问题3:ROC曲线如何绘制?
回答3:一条曲线的绘制必须是多个点的连线,那么我们就需要在坐标轴上描出多个点,以此来绘制ROC曲线,具体步骤如下:
(1)假设我们有一个100行的数据集,按照9:1划分为训练集和测试集;
(2)接下来我们建立二分类模型并预测结果,这时10行的测试集中每个观测都应该有一个对应的原始分类和预测概率;
测试集
原始分类
预测概率
测试集
原始分类
预测概率
1
P
0.9
6
P
0.49
2
P
0.8
7
N
0.38
3
N
0.7
8
N
0.31
4
P
0.6
9
P
0.3
5
P
0.54
10
N
0.1
(4)这时我们依次将10个预测概率作为阈值threshold,当准确度大于或等于这个值的时候,预测结果为P,否则为N,例如,预测概率值为0.6,那么测试集结果为:
测试集
原始分类
预测分类
测试集
原始分类
预测分类
1
P
P
6
P
N
2
P
P
7
N
N
3
N
P
8
N
N
4
P
P
9
P
N
5
P
N
10
N
N
由此绘制混淆矩阵:
计算TPR与FPR:
TPR = TP/(TP+FN) = 0.3/(0.3+0.3) = 0.5
FPR = FP/(FP+TN) = 0.3/(0.1+0.3) = 0.75
据此,我们每更换一次阈值threshold,就能计算出一组TPR与FPR,那么这个数据集就应该能计算出10组TPR与FPR(其余9组请同学自行推算,不再写出具体计算过程)
(5)由此,我们以FPR为横坐标,TPR为纵坐标,描出所有的坐标点并连线,最终汇出ROC曲线,这里给出ROC曲线样例如下:
13 Oct 2017
非线性回归相较于线性回归而言,总带有一丢丢复杂的神秘感。关于线性回归模型相信各位已耳熟能详,因此这里主要讨论非线性回归模型。其实非线性回归中很大一部分是基于多项式的回归模型,即利用曲线方程代替直线方程拟合坐标图上各点,使得各点到曲线的距离总和最短。
一元m次多项式回归方程为:
二元二次多项式回归方程为:
多项式回归的最大优点就是可以通过增加x的高次项对实测点进行逼近,直至满意为止。事实上,多项式回归可以处理很大一类非线性问题,它在分析中占有重要的地位,因为任何一个函数都可以分段用多项式来逼近。
举一个房屋价格与房屋尺寸非线性拟合的实例,数据集下载地址:prices.txt
· 算法构建代码
# python -version 3.5+
import matplotlib.pyplot as plt
import numpy as np
from sklearn import linear_model
from sklearn.preprocessing import PolynomialFeatures
# 读取数据集
datasets_X = [] #建立datasets_X储存房屋尺寸数据
datasets_Y = [] #建立datasets_Y储存房屋成交价格数据
fr = open('E:\\prices.txt', 'r', encoding='utf-8') #指定prices.txt数据集所在路径
lines = fr.readlines() #读取一整个文件夹
for line in lines: #逐行读取,循环遍历所有数据
items = line.strip().split(",") #变量之间按逗号进行分隔
datasets_X.append(int(items[0])) #读取的数据转换为int型
datasets_Y.append(int(items[1]))
# 数据预处理
length = len(datasets_X)
datasets_X = np.array(datasets_X).reshape([length, 1]) #将datasets_X转化为数组
datasets_Y = np.array(datasets_Y)
minX = min(datasets_X) #以数据datasets_X的最大值和最小值为范围,建立等差数列,方便后续画图
maxX = max(datasets_X)
X = np.arange(minX, maxX).reshape([-1, 1])
# 数据建模
poly_reg = PolynomialFeatures(degree=2) #degree=2表示二次多项式
X_poly = poly_reg.fit_transform(datasets_X) #构造datasets_X二次多项式特征X_poly
lin_reg_2 = linear_model.LinearRegression() #创建线性回归模型
lin_reg_2.fit(X_poly, datasets_Y) #使用线性回归模型学习X_poly和datasets_Y之间的映射关系
· 测试结果代码
# 查看回归系数
print('Coefficients:',lin_reg_2.coef_)
# 查看截距项
print('intercept:',lin_reg_2.intercept_)
# 数据可视化
plt.scatter(datasets_X, datasets_Y, color='orange')
plt.plot(X, lin_reg_2.predict(poly_reg.fit_transform(X)), color='blue')
plt.xlabel('Area')
plt.ylabel('Price')
plt.show()
· 部分结果展示
相关系数Coefficients: [ 0.00000000e+00 4.93982848e-02 1.89186822e-05]
截距项intercept: 151.846967505
非线性回归公式:Y = 151.8470 + 4.9398e-02*x + 1.8919e-05*x^2
非线性拟合图:
30 Aug 2017
逻辑回归(Logistic Regression)是比较常见的机器学习算法之一,与SVM支持向量机类似,属于典型的 二分类算法。但逻辑回归相较于SVM的优点在于,前者不仅能够预测某事件是否将会发生,还包含该事件发生的可能性。例如想要知道张三是否会购买产品A,SVM所预测的结果只能告诉你,张三会购买或者不会购买,但逻辑回归能告诉你,张三有70%的概率购买产品A,从而你可以根据自己的业务设置风险率阀值。
关于逻辑回归的数学公式百度、Google已经有很好的解答,遂不再赘述。本博文主要介绍如何利用Python实现逻辑回归算法,该算法并没有引用sklearn包,因此具有一定的复杂度,但所实现的算法具有相当高的灵活性,适用于大规模数据分析系统的开发。
偏好使用sklearn的朋友,请跳转:sklearn主要模块和基本使用
输入数据集下载地址:训练集train,测试集test,预测集predict.txt
· 算法构建代码
# python -version 3.5+
import numpy as np
from numpy import *
## 构建sigmoid函数
def sigmoid(x):
return .5 * (1 + np.tanh(.5 * x))
## 训练逻辑回归模型
def trainLogRegres(train_x, train_y, opts):
# 构建训练样本
numSamples, numFeatures = shape(train_x)
alpha = opts['alpha']
maxIter = opts['maxIter']
weights = ones((numFeatures, 1))
# 选择最优的梯度下降法
for k in range(maxIter):
if opts['optimizeType'] == 'gradDescent': # 梯度下降法
output = sigmoid(train_x * weights)
error = train_y - output
weights = weights + alpha * train_x.transpose() * error
elif opts['optimizeType'] == 'stocGradDescent': # 随机梯度下降法
for i in range(numSamples):
output = sigmoid(train_x[i, :] * weights)
error = train_y[i, 0] - output
weights = weights + alpha * train_x[i, :].transpose() * error
elif opts['optimizeType'] == 'smoothStocGradDescent': # 平稳随机梯度下降法
dataIndex = list(range(numSamples))
for i in range(numSamples):
alpha = 4.0 / (1.0 + k + i) + 0.01
randIndex = int(random.uniform(0, len(dataIndex)))
output = sigmoid(train_x[randIndex, :] * weights)
error = train_y[randIndex, 0] - output
weights = weights + alpha * train_x[randIndex, :].transpose() * error
del (dataIndex[randIndex])
else:
raise NameError('Not support optimize method type!')
return weights
## 检验逻辑回归模型
def testLogRegres(weights, test_x, test_y):
numSamples, numFeatures = shape(test_x)
matchCount = 0
for i in range(numSamples):
predict = sigmoid(test_x[i, :] * weights)[0, 0] > 0.5 #设置阀值为0.5
if predict == bool(test_y[i, 0]):
matchCount += 1
accuracy = float(matchCount) / numSamples
return accuracy
## 预测逻辑回归模型
def preLogRegres(weights ,pre_x):
numSamples, numFeatures = shape(pre_x)
outfile = open('D://predict_result.txt', 'w') # 将概率值输出到文件
for i in range(numSamples):
predict = sigmoid(pre_x[i, :] * weights)[0, 0]
predict_m = sigmoid(pre_x[i, :] * weights)[0, 0] > 0.5 #是否阀值定为0.5
outfile.write(str(predict)+'\n')
print(str(predict_m) + ' ' + str(predict)) #同时输出是否及概率值
outfile.close()
· 测试结果代码
## step 1: 模型训练
def loadData(): # 载入训练集
train_x = []
train_y = []
fileIn = open('D://train.txt')
for line in fileIn.readlines():
lineArr = line.split() #设置分隔符
train_x.append([1.0, float(lineArr[0]), float(lineArr[1])])
train_y.append(float(lineArr[-1]))
return mat(train_x), mat(train_y).transpose()
fileIn.close()
train_x, train_y = loadData()
opts = {'alpha': 0.01, 'maxIter': 20, 'optimizeType': 'smoothStocGradDescent'} # 参数设置
optimalWeights = trainLogRegres(train_x, train_y, opts)
## step 2: 模型检验
def loadData1():
test_x = []
test_y = []
fileIn = open('D://test.txt')
for line in fileIn.readlines():
lineArr = line.split()
test_x.append([1.0, float(lineArr[0]), float(lineArr[1])])
test_y.append(float(lineArr[-1]))
return mat(test_x), mat(test_y).transpose()
fileIn.close()
test_x, test_y = loadData1()
accuracy = testLogRegres(optimalWeights, test_x, test_y)
print('模型预测精度:' + str(accuracy))
print('================================')
## step 3: 模型预测
def loadData2():
pre_x = []
fileIn = open('D://predict.txt')
for line in fileIn.readlines():
lineArr = line.split()
pre_x.append([1.0, float(lineArr[0]), float(lineArr[1])])
return mat(pre_x)
fileIn.close()
pre_x = loadData2()
print('模型预测结果:')
predict = preLogRegres(optimalWeights, pre_x)
· 部分结果展示
模型预测精度:0.9215686274509803
================================
模型预测结果:
True 0.969439134428
False 0.0121320687856
True 0.999891075052
False 0.0276136702724
True 0.948171859849
True 0.999981963204
True 0.960074174269
True 0.999639571954
True 0.999979133078
True 0.99509838304
True 0.999965399666
True 0.999948401765
False 0.00443630610109
···