def predict(train_samples,X):
    #描述属性分别用数字代替
    #年龄: <=30:0, 30~40:1, <40:2
    #收入:‘低’:0,'中':1,'高':2
    #是否学生:‘是’:1,'否':1
    #信誉: '中':0,'优':1
    #购买属性用数字代替
    #购买电脑 :‘是’:0,‘否’:1
    MAP = [{'<=30': 0,'31~40' : 1, '>40': 2},
           {'低': 0,'中': 1,'高':2},
           {'是':0, '否':1},
           {'中':0, '优':1},
           {'是':0,'否':1}]
    #下面步骤将文字转化为对应的数字
    train_samples = [sample.split(' ') for sample in train_samples]
    train_samples = [[MAP[i][attr] for i,attr in enumerate(sample)]for sample in train_samples]
    X = [MAP[i][attr] for i , attr in enumerate(X.split(' '))]
    #训练样本数量
    n_sample = len(train_samples)
    #单个样本的维度,描述属性和类型属性个数
    dim_sample = len(train_samples[0])
    #计算每个属性的取值
    attr = []
    for i in range(0,dim_sample):
        attr.append([])
    for sample in train_samples:
        for i in range(0,dim_sample):
            if sample[i] not in attr[i]:
                attr[i].append(sample[i])
    #每个属性取值的个数
    n_attr = [len(attr) for atttr in attr]
    #记录不同类别的样本个数
    n_c = []
    for i in range(0,n_attr[dim_sample-1]):
        n_c.append(0)
    #计算不同类别的样本个数
    for sample in train_samples:
        n_c[sample[dim_sample-1]] += 1
    #计算不同类别样本所占比例
    p_c = [n_cx / sum(n_c) for n_cx in n_c]
    #将用户按类别分类
    samples_at_c = {}
    for c in attr[dim_sample-1]:
        samples_at_c[c] = []
    for sample in train_samples:
        samples_at_c[sample[dim_sample-1]].append(sample)
    #记录每个类别的训练样本中,待取分类样本的某个属性值的样本个数
    n_attr_X = {}
    for c in attr[dim_sample-1]:
        n_attr_X[c] = []
        for j in range(0,dim_sample-1):
            n_attr_X[c].append(0)
    #计算每个类别的训练样本中待取分类样本的某个属性值的样本个数
    for c, samples_at_cx in zip(samples_at_c.keys(), samples_at_c.values()):
        for sample in samples_at_cx:
            for i in range(0,dim_sample-1):
                if X[i] == sample[i]:
                    n_attr_X[c][i] = n_attr_X[c][i]+1
    #字典转化为list
    n_attr_X = list(n_attr_X.values())
    n_attr_X[0],n_attr_X[1] = n_attr_X[1],n_attr_X[0]
    #储存最后的概率
    result_p =[]
    for i in range(0,n_attr[dim_sample-1]):
        result_p.append(p_c[i])
    #计算概率
    for i in range(0,n_attr[dim_sample-1]):
        n_attr_X[i] = [x/n_c[i] for x in n_attr_X[i]]
    for x in n_attr_X[i]:
        result_p[i] *= x
    #找到概率对应最大的类别,便是样本的分类情况
    predict_class = result_p.index(max(result_p))
    predict_list.append(predict_class)
    return predict_class
if __name__=='__main__':
    #训练样本
    train_samples =  ["<=30 高 否 中 否",
                     "<=30 高 否 优 否",
                     "31~40 高 否 中 是",
                     ">40 中 否 中 是",
                     ">40 低 是 中 是",
                     ">40 低 是 优 否",
                     "31~40 低 是 优 是",
                     "<=30 中 否 中 否",
                     "<=30 低 是 中 是",
                     ">40 中 是 中 是",
                     "<=30 中 是 优 是",
                     "31~40 中 否 优 是",
                     "31~40 高 是 中 是",
                     ">40 中 否 优 否" ]
    #待分类样本
    X = '<=30 中 是 中'
    #实现待分类样本的预测
    print(predict(train_samples,X))
    #实现评价指标
    truth=false=0
    new_train_samples = ["<=30 高 否 中 否",
                     "<=30 高 否 优 否",
                     "31~40 高 否 中 是",
                     ">40 中 否 中 是",
                     ">40 低 是 中 是",
                     ">40 低 是 优 否",
                     "31~40 低 是 优 是",
                     "<=30 中 否 中 否",
                     "<=30 低 是 中 是",
                     ">40 中 是 中 是",
                     "<=30 中 是 优 是",
                     "31~40 中 否 优 是",
                     "31~40 高 是 中 是",
                     ">40 中 否 优 否" ]
    for index,train_sample in enumerate(train_samples):
          X=train_sample[:-2]
          print(X)
          res=train_sample[-1]
          #将原训练集每次拿出一个训练样本作为测试样本,其余为新的训练集
          new_train_samples.pop(index)
          predict_res=predict(new_train_samples,X)[0]
          print (predict_res)
          if (res=='是')&(predict_res==0):
              truth+=1
          elif(res=='否')&(predict_res==1):
               truth+=1
          else:
               false+=1
          new_train_samples = ["<=30 高 否 中 否",
                     "<=30 高 否 优 否",
                     "31~40 高 否 中 是",
                     ">40 中 否 中 是",
                     ">40 低 是 中 是",
                     ">40 低 是 优 否",
                     "31~40 低 是 优 是",
                     "<=30 中 否 中 否",
                     "<=30 低 是 中 是",
                     ">40 中 是 中 是",
                     "<=30 中 是 优 是",
                     "31~40 中 否 优 是",
                     "31~40 高 是 中 是",
                     ">40 中 否 优 否" ]
          truth_per= truth/(truth+false)
          print(truth,false)
          print(truth_per)

2020-05-27·