AMS算法 大数据实验4

AMS算法

实验要求:

使用自己所擅长的程序语言编写AMS算法(估计数据流元素的二阶矩)。假设所有元素为1-n,mi表示元素i的出现次数(在整个文件中的出现次数),则二阶矩等于(m1)2+(m2)2+(m3)2+…+(mn)2。

实验步骤:

1:以stream_for_ams.txt文件为自己所写程序的输入,读取文件中数据(数值范围是1-105);
2:请编写一个精确算法A,来计算整个文件stream_for_ams.txt中所有数据的二阶矩的真实值(179866);
3:假设文件中的数据为e1,e2,e3,…,eN,设采样点个数为n个,即随机从数据中选取1个位置后,利用AMS算法计算估计的二阶矩值(参看书第二版,112页);
4:使用书上110页(组合估计)的技巧;假设有m分组,每个分组包含n个位置;对于每组计算二阶矩估计的平均值作为改组的二阶矩估计,然后用m个组的二阶矩估计的中位数,作为最终的二阶矩估计值;

5:设真实的二阶矩为M, 令m=1,n=1, 重复实验步骤4,20次,可以得到20个的估计值(二阶矩)M1 M2 ,…,M20,计算平均误差error_sum ={[ (M1-M)2+( M2-M)2+( M3-M)2+…++( M20-M)2]/20}0.5;
6:令m=10,n=10, 重复步骤,比较当m=1,n=1时的平均误差与m=10,n=10的平均误差。
7: 在数据流长度未知的情况下,给定选择位置个数100(样本集合大小),综合水库采样算法和ams算法,设计编写新的算法,该算法在任意时刻都可以给出数据流中当前元素二阶矩的估计;

实验考察要求:

1:分析并讲解自己所编写程序;
2:分析m=1,n=1时和m=10,n=10时,平均误差有区别的原因;
3:结合ams和水库算法,编写出可以处理数据大小未知的情况的二阶矩估计算法;

真实二阶矩值

def Count_accurate():
    data_flu = {}
    sum=0
    with open("stream_for_ams.txt",'r') as f:
        while True:
            temp = f.readline()
            if temp =='':
                break
            temp=int(temp.strip())
            if temp in data_flu:
                data_flu[temp]+=1
            else:
                data_flu[temp]=1
    for i in data_flu.values():
        sum+=i**2
    return sum
       
print(Count_accurate())
1798766
a = {1:2,3:4}
a[1]=5
print(a)
print(2 in a)
{1: 5, 3: 4}
False

统计整个数据流的长度

def Count_length():
    sum=0
    with open("stream_for_ams.txt",'r') as f:
        while True:
            temp = f.readline()
            if temp =='':
                break
            sum+=1
    return sum
print(Count_length())
350000

单个随机数的估计

import random
def Count_estimate():
    data_flu = {}
    sum=0
    count =0
    flag =0
    n =Count_length()
    x = random.randint(1,n)
    with open("stream_for_ams.txt",'r') as f:
        while True:
            temp = f.readline()
            if temp =='':
                break
            count+=1
            if count<x:
                continue
            temp=int(temp.strip())
            if flag==0:
                data_flu[temp]=0          
                flag =1
            if temp in data_flu:
                data_flu[temp]+=1

    for i in data_flu.values():
        value = n*(2*i-1)
    return value
print(Count_estimate())
1050000

m,n的估计

import random
#不考虑随机到的下标代表的值相同的情况
def Count_estimate_1(m,l):
    data_flu = {}
    sum=0
    count =0#用来记录当前数据流中的访问节点
    value_ml = []
    n =Count_length()   
    R_average=[]
    random_x_index=[]
    for i in range(m*l):
        x = random.randint(1,n)
        random_x_index.append(x)
    random_x_index.sort() #对随机出来的下标进行排序
    # print(random_x_index)
    count1=0#用来记录访问到的随机位置的下标        
    count2=0
    flag =0
    with open("stream_for_ams.txt",'r') as f:
        while True:
            temp = f.readline()
            if temp =='':
                break
            count+=1
            temp=int(temp.strip())
            if count==random_x_index[count1]:
                flag=1#说明出现了第一个要找到下标
                count1+=1#进入下一个下标的对比
                if count1==len(random_x_index):#为了防止最后一个下标加一之后产生越界
                    count1-=1                             
                if temp in data_flu:
                    data_flu[temp]+=1          
                else:
                    data_flu[temp]=1
                continue#如果这里加入了,下面的就不要加了,直接进入下一个数
            if flag==1:#小于 第一个要加入的下标都不计入
                if temp in data_flu: #在的就加一,不在的就不管,只统计随机到的数
                    data_flu[temp]+=1  
    # print(list(data_flu.values()))              
    for i in data_flu.values():
        value_ml.append(i)
        print(i)
    for i in value_ml:
        estm = n*(2*i-1)
        sum+=estm
        count2+=1
        if count2%l ==0:
            R_average.append(sum/l)
            sum = 0
    R_average.sort()
    R_middle = R_average[len(R_average)//2]
    
    return R_middle
print(Count_estimate_1(2,2))
5
2
2
2
2100000.0

对于m,l算法的改进

import random
#考虑到随机到的下标代表的值相同的情况  同时修复了随机到相同地方会出现bug的问题
def Count_estimate_2(m,l):
    data_flu = []#用来记录不同下标随机到的数出现的次数 [[index,value,count].....]
    sum=0
    count =0#用来记录当前数据流中的访问节点
    value_ml = []
    n =Count_length()   
    R_average=[]
    random_x_index=[]
    for i in range(m*l):
        x = random.randint(1,n)
        random_x_index.append(x)
    random_x_index.sort() #对随机出来的下标进行排序
    # print(random_x_index)
    count1=0#用来记录访问到的随机位置的下标        
    count2=0
    flag =0
    with open("stream_for_ams.txt",'r') as f:
        while True:
            temp = f.readline()
            if temp =='':
                break
            count+=1
            temp=int(temp.strip())
            while count==random_x_index[count1]:#这里用while表示如果遇到了相同的下标,那就接着后移,加入到记录当中
                flag=1#说明出现了第一个要找到下标
                data_flu.append([count,temp,0])
                for i in data_flu:
                    if temp==i[1]:
                        i[2]+=1
                count1+=1#进入下一个下标的对比
                if count1==len(random_x_index):#为了防止最后一个下标加一之后产生越界
                    count1-=1
                    break #防止访问到最后一个元素的时候死循环                                        
                continue#如果这里加入了,下面的就不要加了,直接进入下一个数
            if flag==1:#小于 第一个要加入的下标都不计入
                for i in data_flu:
                    if temp==i[1]:
                        i[2]+=1
    # print(list(data_flu.values()))              
    for i in data_flu:
        value_ml.append(i[2])
        # print(i[2])
    for i in value_ml:
        estm = n*(2*i-1)
        sum+=estm
        count2+=1
        if count2%l ==0:
            R_average.append(sum/l)
            sum = 0
    R_average.sort()
    R_middle = R_average[len(R_average)//2]
    
    return R_middle
# print(Count_estimate_2(2,2))
def error_sum(m,l,t):
    sum=0
    real_value = Count_length()
    for i in range(t):
        print(Count_estimate_2(m,l))
        sum+=(Count_estimate_2(m,l)-real_value)
    return sum/t

print("(1,1)重复20次 的平均误差值是",error_sum(1,1,20))
9450000.0
3850000.0
1050000.0
1750000.0
1050000.0
2450000.0
1750000.0
1050000.0
3150000.0
1050000.0
2450000.0
1050000.0
2450000.0
1050000.0
3850000.0
1750000.0
1750000.0
3150000.0
1050000.0
2450000.0
(1,1)重复20次 的平均误差值是 2100000.0
def error_sum(m,l,t):
    sum=0
    real_value = Count_length()
    for i in range(t):
        print(Count_estimate_2(m,l))
        sum+=(Count_estimate_2(m,l)-real_value)**2
    return (sum/t)**0.5

print("(1,1)重复20次 的方差值是",error_sum(1,1,20))
1050000.0
2450000.0
3850000.0
3150000.0
1050000.0
1750000.0
1050000.0
1750000.0
15750000.0
1050000.0
1050000.0
3150000.0
1750000.0
1750000.0
3150000.0
1050000.0
2450000.0
3150000.0
1750000.0
1050000.0
(1,1)重复20次 的方差值是 2016680.4407243107
def error_sum(m,l,t):
    sum=0
    real_value = Count_length()
    for i in range(t):
        print(Count_estimate_2(m,l))
        sum+=(Count_estimate_2(m,l)-real_value)**2
    return (sum/t)**0.5

print("(20,20)重复20次 的方差值是",error_sum(10,10,20))
2450000.0
2240000.0
2310000.0
3080000.0
2170000.0
2520000.0
3360000.0
2240000.0
3010000.0
2940000.0
2660000.0
2310000.0
2380000.0
2520000.0
2170000.0
2520000.0
2380000.0
2380000.0
2450000.0
3150000.0
(20,20)重复20次 的方差值是 2146673.007237013

ams算法和水库采样算法的结合

算法思想:维持一个s的窗口大小,数据流长度小于s的时候,直接填进去,维持一个统计各个数频次的数组,超过s的时候,,这个时候开始以s/t的概率进行替换,要是替换成功就加到数组里面,,没替换成功,就看维持的数组里面是否有这个数,有的话,相应的元素计数加一

import random
#考虑到随机到的下标代表的值相同的情况  同时修复了随机到相同地方会出现bug的问题
def Count_estimate_anytime(s,t):
    data_flu = []#用来记录不同下标随机到的数出现的次数 [[index,value,count].....]
    sum=0
    value_ml = []       
    with open("stream_for_ams.txt",'r') as f:
        if t<=s:
            for i in range(t):
                temp = f.readline()
                temp=int(temp.strip())
                data_flu.append([i+1,temp,0])
                for single in data_flu:
                    if temp==single[1]:
                        single[2]+=1   
        else:  
            for i in range(t):
                temp = f.readline()
                temp=int(temp.strip())
                data_flu.append([i+1,temp,0])
                for single in data_flu:
                    if temp==single[1]:
                        single[2]+=1 
            for i in range(s+1,t+1):
                temp = f.readline()
                if temp=='':
                    print("文件读空或者当前超过文件最大长度")
                    return 0
                temp=int(temp.strip())  
                x = random.randint(1,t)
                if x<=s:
                    data_flu[x]=[i,temp,0]
                    for single in data_flu:
                        if temp==single[1]:
                            single[2]+=1 
                else:
                    for single in data_flu:
                            if temp==single[1]:
                                single[2]+=1     

    # print(list(data_flu.values()))              
    for i in data_flu:
        value_ml.append(i[2])
        # print(i[2])
    for i in value_ml:
        estm = t*(2*i-1)
        sum+=estm

    return sum/(len(value_ml))
# print(Count_estimate_2(2,2))

任意时刻的真实的二阶矩阵

def Count_accurate_anytime(t):
    data_flu = {}
    sum=0
    with open("stream_for_ams.txt",'r') as f:
        for i in range(1,t+1):
            temp = f.readline()
            if temp=='':
                print("文件读空或者当前超过文件最大长度")
                return 0
            temp=int(temp.strip())  
            if temp in data_flu:
                data_flu[temp]+=1
            else:
                data_flu[temp]=1          
    for i in data_flu.values():
        sum+=i**2
    return sum
       
s= int(input("请输入当前的窗口大小值:"))
t = int(input("请输入当前的时间:"))
print("当前窗口的大小是",s)
print("当前的时间戳是",t)
print("当前时刻精确的二阶估计矩阵值是:",Count_accurate_anytime(t))
print("当前的算法估计的二阶矩阵是",Count_estimate_anytime(s,t))
print("当前算法的误差是",abs(Count_accurate_anytime(t)-Count_estimate_anytime(s,t))/Count_accurate_anytime(t))
当前窗口的大小是 100
当前的时间戳是 3000
当前时刻精确的二阶估计矩阵值是: 3128
当前的算法估计的二阶矩阵是 3312.0
当前算法的误差是 0.05690537084398977
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值