机器学习实战——第十五章-MapReduce

import sys
from numpy import mat, mean, power
'''
首先是从文件中读取内容,然后遍历每一行,返回line.rstrip() 的值到生成器中,生成器的大小是文件的行数。
其中rstrip() 是返回该行删除 string 字符串末尾后的指定字符(默认为空格)
'''
def read_input(file):
    for line in file:#按行读取文件
        yield line.rstrip()#yield首先是个关键词,类似于return,返回的是个生成器
'''
生成器是一个特殊的程序,可以被用作控制循环的迭代行为,python中生成器是迭代器的一种,使用yield返回值函数,
每次调用yield会暂停,而可以使用next()函数和send()函数恢复生成器。
生成器类似于返回值为数组的一个函数,这个函数可以接受参数,可以被调用,但是,不同于一般的函数会一次性返回包括了所有数值的数组,
生成器一次只能产生一个值,这样消耗的内存数量将大大减小,
而且允许调用函数可以很快的处理前几个返回值,因此生成器看起来像是一个函数,但是表现得却像是迭代器
'''
input =read_input(sys.stdin)  # creates a list of input lines,读取文件,创建一个输入行列表
input = [float(line) for line in input]  # overwrite with floats按行读取输入,创建一组对应的浮点数
numInputs = len(input)#得到数组的长度
input = mat(input)#把输入变为矩阵
sqInput =power(input, 2)#所有值变为平方
print("%d\t%f\t%f" % (numInputs,mean(input), mean(sqInput)))  # calc mean of columns
#print >> sys.stderr, "report: still alive"
X: print("fatal error", file=sys.stderr)

对于Windows, 1.win+R

2.然后输入cmd

3.使用cd \ 把目标返回到最上面,使用cd 转到你保存mrMeanMapper.py的地方,

4.输入

5.得到结果

import sys
from numpy import mat, mean, power

def read_input(file):
    for line in file:
        yield line.rstrip()

input = read_input(sys.stdin)#creates a list of input lines

#split input lines into separate items and store in list of lists
mapperOut = [line.split('\t') for line in input]

#accumulate total number of samples, overall sum and overall sum sq
cumVal=0.0
cumSumSq=0.0
cumN=0.0
for instance in mapperOut:
    nj = float(instance[0])#第一个字段是数据个数
    cumN += nj#总数
    cumVal += nj*float(instance[1])#第二个字段是一个map输出的均值,均值乘以数据个数就是数据总和
    cumSumSq += nj*float(instance[2])#第三个字段是一个map输出的平方和的均值,乘以元素个数就是所有元素的平方和
    
#calculate means
mean = cumVal/cumN#得到所有元素的均值
varSum=(cumSumSq-2*mean*cumVal+cumN*mean*mean)/cumN

#output size, mean, mean(square values)
print ("%d\t%f\t%f" % (cumN, mean, varSum))
#print >> sys.stderr, "report: still alive"
X: print("fatal error", file=sys.stderr)
import mrjob
from mrjob.job import MRJob

class MRmean(MRJob):
    def __init__(self, *args, **kwargs):
        super(MRmean, self).__init__(*args, **kwargs)
        self.inCount = 0
        self.inSum = 0
        self.inSqSum = 0
    
    def map(self, key, val): #needs exactly 2 arguments#类似于for循环,在每行输入上执行同样的步骤
        if False: yield
        inVal = float(val)
        self.inCount += 1
        self.inSum += inVal
        self.inSqSum += inVal*inVal
#mapper() 中对输入值进行积累,所有值收集完毕后计算出均值和平方均值,最后把这些值作为中间值通过yield传出去
    def map_final(self):
        mn = self.inSum/self.inCount
        mnSq = self.inSqSum/self.inCount
        yield (1, [self.inCount, mn, mnSq])#所有的mapper都使用1作为key,因为希望所有的中间值在同一个reducer里加起来

    def reduce(self, key, packedValues):
        cumVal=0.0; cumSumSq=0.0; cumN=0.0
        for valArr in packedValues: #get values from streamed inputs
            nj = float(valArr[0])
            cumN += nj
            cumVal += nj*float(valArr[1])
            cumSumSq += nj*float(valArr[2])
        mean = cumVal/cumN
        var = (cumSumSq - 2*mean*cumVal + cumN*mean*mean)/cumN
        yield (mean, var) #emit mean and var
     #为mrjob指定mapper和reducer的名称
    def steps(self):
        return ([self.mr(mapper=self.map, mapper_final=self.map_final,\
                          reducer=self.reduce,)])

if __name__ == '__main__':
    MRmean.run()
from numpy import *

def loadDataSet(fileName):#加载数据
    dataMat = []; labelMat = []
    fr = open(fileName)
    for line in fr.readlines():
        lineArr = line.strip().split('\t')
        #dataMat.append([float(lineArr[0]), float(lineArr[1]), float(lineArr[2])])
        dataMat.append([float(lineArr[0]), float(lineArr[1])])
        labelMat.append(float(lineArr[2]))
    return dataMat,labelMat

def seqPegasos(dataSet, labels, lam, T):#T代表迭代次数,k代表待处理数据的大小
    m,n = shape(dataSet); w = zeros(n)#初始化
    for t in range(1, T+1):#迭代循环
        i = random.randint(m)#random.randint(a,b)用于生成一个指定范围内的整数
        eta = 1.0/(lam*t)#更新eta
        p = predict(w, dataSet[i,:])#权重乘以数据
        if labels[i]*p < 1:#被错分了
            w = (1.0 - 1/t)*w + eta*labels[i]*dataSet[i,:]
        else:
            w = (1.0 - 1/t)*w
        print (w)
    return w
        
def predict(w, x):
    return w*x.T

def batchPegasos(dataSet, labels, lam, T, k):
    m,n = shape(dataSet); w = zeros(n)
    dataIndex = list(range(m))
    for t in range(1, T+1):
        wDelta = mat(zeros(n)) #reset wDelta
        eta = 1.0/(lam*t)
        random.shuffle(dataIndex)
        for j in range(k):#go over training set 
            i = dataIndex[j]
            p = predict(w, dataSet[i,:])        #mapper code
            if labels[i]*p < 1:                 #mapper code
                wDelta += labels[i]*dataSet[i,:].A #accumulate changes  
        w = (1.0 - 1/t)*w + (eta/k)*wDelta       #apply changes at each T
    return w

datArr,labelList = loadDataSet('testSet.txt')
datMat = mat(datArr)
#finalWs = seqPegasos(datMat, labelList, 2, 5000)
finalWs = batchPegasos(datMat, labelList, 2, 50, 100)
print (finalWs)

import matplotlib
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
x1=[]; y1=[]; xm1=[]; ym1=[]
for i in range(len(labelList)):
    if labelList[i] == 1.0:
        x1.append(datMat[i,0]); y1.append(datMat[i,1])
    else:
        xm1.append(datMat[i,0]); ym1.append(datMat[i,1])
ax.scatter(x1, y1, marker='s', s=90,c='blue')
ax.scatter(xm1, ym1, marker='o', s=50, c='red')
x = arange(-6.0, 8.0, 0.1)
y = (-finalWs[0,0]*x - 0)/finalWs[0,1]
#y2 = (0.43799*x)/0.12316
y2 = (0.498442*x)/0.092387 #2 iterations
ax.plot(x,y)
ax.plot(x,y2,'g-.')
ax.axis([-6,8,-4,5])
ax.legend(('50 Iterations', '2 Iterations') )
plt.show()

 

import mrjob
from mrjob.job import MRJob
import pickle
from numpy import *

class MRsvm(MRJob):
    DEFAULT_INPUT_PROTOCOL = 'json_value'
    
    def __init__(self, *args, **kwargs):
        super(MRsvm, self).__init__(*args, **kwargs)
        self.data = pickle.load(open('G:\python\python code\MLinactive\svmDat27'))#添加数据
        self.w = 0
        self.eta = 0.69
        self.dataList = []
        self.k = self.options.batchsize
        self.numMappers = 1
        self.t = 1  #iteration number
                                                 
    def configure_options(self):
        super(MRsvm, self).configure_options()
        self.add_passthrough_option(
            '--iterations', dest='iterations', default=2, type='int',
            help='T: number of iterations to run')
        self.add_passthrough_option(
            '--batchsize', dest='batchsize', default=100, type='int',
            help='k: number of data points in a batch')

    '''
    程序清单15-6里的第一个方法是map ( ),
    这也是分布式的部分,它得到输人值并存储,以便
    在map_fin()中处理。该方法支持三种类型的输人:
    w向量、七或者xo七是迭代次数,在本方法
    中不参与运算。
    状态不能保存,因此如果需要在每次迭代时保存任何变量并留给下一次迭代,可
    以使用key/value对传递该值,
    抑或是将其保存在磁盘上。显然前者更容易实现,速度也更快。
    map_fin()方法在所有输人到达后开始执行。
    这时已经获得了权重向量w和本次批处理中的
    而是索引。数据存储在磁盘上,当脚本执行
    一组x值。每个x值是一个整数,它并不是数据本身,而是索引。数据仔储在1}}上,}n}}
    的时候读人到内存中。当map_fin()启动时,它首先将数据分成标签和数据,然后在本次批
    的数据(存储在self.dataList里)上进行迭代,如果有任何值被错分就将其输出给redui
    w向量和t值都应被发送给reducero
        

    '''
    # 得到输入值并进行存储 支持三种类型的输入:w向量 t或者x      t是迭代次数,在该方法中不参与计算
    # 状态不能保存,因此如果需要在每次迭代时保存任何变量并留给下一次迭代,可以使用key/value对传递该值,抑或是保存在磁盘上。前者较易实现,速度也更快

    def map(self, mapperId, inVals): #needs exactly 2 arguments分布式部分,它得到输人值并存储,以便
    #在map_fin()中处理。该方法支持三种类型的输人:w向量、t或者x, t是迭代次数,在本方法中不参与运算。
        #input: nodeId, ('w', w-vector) OR nodeId, ('x', int)
        if False: yield
        if inVals[0]=='w':                  #accumulate W-vector
            self.w = inVals[1]
        elif inVals[0]=='x':
            self.dataList.append(inVals[1])#accumulate data points to calc
        elif inVals[0]=='t': self.t = inVals[1] 
        else: self.eta=inVals #this is for debug, eta not used in map

    '''  
     map_fin()
     方法在所有输人到达后开始执行。
     这时已经获得了权重向量w和本次批处理中的
     而是索引。数据存储在磁盘上,当脚本执行
    一组x值。每个x值是一个整数,它并不是数据本身,而是索引。数据仔储在1}}上,}n}}
    的时候读人到内存中。当map_fin()
    启动时,它首先将数据分成标签和数据,然后在本次批
    的数据(存储在self.dataList里)
    上进行迭代,如果有任何值被错分就将其输出给redui
    w向量和t值都应被发送给reducero
    '''
    def map_fin(self):
        labels = self.data[:,-1]; X=self.data[:,0:-1]#reshape data into X and Y
        if self.w == 0: self.w = [0.001]*shape(X)[1] #init w on first iteration
        for index in self.dataList:
            p = mat(self.w)*X[index,:].T #calc p=w*dataSet[key].T 
            if labels[index]*p < 1.0:
                yield (1, ['u', index])#make sure everything has the same key                           
        yield (1, ['w', self.w])       #so it ends up at the same reducer
        yield (1, ['t', self.t])
    '''
     最后是reduce()函数,对应本例只有一个reducer执行。该函数首先迭代所有的key/value对
     并将值解包到一个局部变量datalist里。之后dataList里的值都将用于更新权重向量w,更新
     量在wDel七a中完成累加.。然后,wMa七按照wDelta和学习率eta进行更新。在what更新完毕后,
     又可以重新开始整个过程:一个新的批处理过程开始,随机选择一组向量并输出。注意,这些向
     量的key是mapper编号。
     '''
    def reduce(self, _, packedVals):
        for valArr in packedVals: #get values from streamed inputs
            if valArr[0]=='u':  self.dataList.append(valArr[1])
            elif valArr[0]=='w': self.w = valArr[1]
            elif valArr[0]=='t':  self.t = valArr[1] 
        labels = self.data[:,-1]; X=self.data[:,0:-1]
        wMat = mat(self.w);   wDelta = mat(zeros(len(self.w)))
        for index in self.dataList:
            wDelta += float(labels[index])*X[index,:] #wDelta += label*dataSet
        eta = 1.0/(2.0*self.t)       #calc new: eta
        #calc new: w = (1.0 - 1/t)*w + (eta/k)*wDelta
        wMat = (1.0 - 1.0/self.t)*wMat + (eta/self.k)*wDelta
        for mapperNum in range(1,self.numMappers+1):
            yield (mapperNum, ['w', wMat.tolist()[0] ]) #emit w
            if self.t < self.options.iterations:
                yield (mapperNum, ['t', self.t+1])#increment T
                for j in range(self.k/self.numMappers):#emit random ints for mappers iid
                    yield (mapperNum, ['x', random.randint(shape(self.data)[0]) ])
        
    def steps(self):
        return ([self.mr(mapper=self.map, reducer=self.reduce, 
                         mapper_final=self.map_fin)]*self.options.iterations)

if __name__ == '__main__':
    MRsvm.run()
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值