<jupyter_start><jupyter_text>This code generates Shapley-CMI valuation results (used to output Table 2)， which are then recorded in {dataset}/{dataset}_data_values.csv.This code also includes the entropy calculation reported in Figure 5.<jupyter_code>import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from scipy.stats import entropy
from sklearn.utils import resample
# load dataset
def load_dataset(name, feature_num, discret_cat=5):
    datafile = './{}/{}.csv'.format(name, name)
    data_pd = pd.read_csv(datafile)
    feature_names = []
    for i in range (1,feature_num+1):
        feature_name = 'f'+str(i)
        if discret_cat > 0: # need discretization
            data_pd[feature_name+'_c'] = pd.cut(data_pd[feature_name], discret_cat, labels = list(range(discret_cat)))
            feature_name += '_c'
        feature_names.append(feature_name)
    data_pd.head()
    y = data_pd['y']
    x = data_pd[feature_names]
    return x, y, feature_names
# for calculating mutual information
from collections import Counter
def our_entropy(labels): # H(A)
    pro_dict = Counter(labels) #计数
    s = sum(pro_dict.values())#总数
    probs = np.array([i/s for i in pro_dict.values()])#概率
    return - probs.dot(np.log(probs))
def MI_(s1,s2):# 互信息
    s_s_1=["%s%s"%(i,j) for i,j in zip(s1,s2)]
    MI_1=our_entropy(s1)+our_entropy(s2)-our_entropy(s_s_1)
    return MI_1
def N_MI(s1,s2): # 标准化互信息
    MI_1 = MI_(s1,s2)
    NMI_1 = MI_1/(our_entropy(s1)*our_entropy(s2))**0.5
    return NMI_1
# get all the permutations of the features and then calculate conditional mutual information regarding Y
import itertools

x, y, feature_names = load_dataset('wine', 13) 
#x, y, feature_names = load_dataset('parkinsons', 22)
#x, y, feature_names = load_dataset('breast', 30)
#x, y, feature_names = load_dataset('spect', 22, 0)
#x, y, feature_names = load_dataset('winequality-red', 11)
#x, y, feature_names = load_dataset('winequality-white', 11)


X_train,X_test,Y_train,Y_test = train_test_split(x, y, test_size=0.2, random_state=0)

# all_feature_permutations = list(itertools.permutations(feature_names)) # time-consuming if feature number is large

contribution = {}
for feature_name in feature_names:
    contribution[feature_name] = []

Y_value_list = Y_train.values.tolist()

# for each_permutation in all_feature_permutations:
random_permutation_times = 10000
for i in range(random_permutation_times): # random sample permutations for certain times
    each_permutation = np.random.permutation(feature_names)
    current_feature_set = []
    current_MI = 0
    for feature_name in each_permutation:
        current_feature_set.append(feature_name)
        x_new = X_train[current_feature_set]
        new_MI = MI_(Y_value_list, list(x_new.itertuples(index=False)))
        contr = new_MI - current_MI # conditional CMI of the current feature in the specific permutation
        contribution[feature_name].append(contr) # add the CMI together in all the permutations
        current_MI = new_MI
    i += 1
    
    if i%100 == 0:
        features_values = [0]*len(feature_names)
        for feature_i in range(len(feature_names)):
            feature_name = feature_names[feature_i]
            features_values[feature_i] = np.mean(contribution[feature_name])
        features_values = np.array(features_values)/np.sum(features_values) #normalization, not necessary, for ease of presentation
        print ('permutation', i, features_values, 'entropy', entropy(features_values)) #entropy to quantify the change of feature values

print("final Shapley-CMI after {} samplings".format(random_permutation_times))
for feature_value in features_values:
    print(feature_value)<jupyter_output>permutation 100 [0.1058653  0.07061077 0.02918043 0.05825907 0.07412079 0.05968489
 0.09429726 0.06477699 0.06309475 0.13181919 0.06854576 0.10537096
 0.07437385] entropy 2.5102387399018364
permutation 200 [0.10604904 0.06393946 0.03508873 0.05630491 0.06066411 0.05549252
 0.10382823 0.0658469  0.0569289  0.11698094 0.08480403 0.10253606
 0.09153616] entropy 2.5138856551307143
permutation 300 [0.10028958 0.06126035 0.03297776 0.05653788 0.05988036 0.062754
 0.1140431  0.06198962 0.05162017 0.10451374 0.086037   0.11125727
 0.09683915] entropy 2.5094467758623797
permutation 400 [0.10411159 0.06412846 0.03418192 0.05737122 0.05644418 0.06369134
 0.10628099 0.06113646 0.05140823 0.10662749 0.08882708 0.10794081
 0.09785025] entropy 2.5118399991501277
permutation 500 [0.09947234 0.05999112 0.03443933 0.05843086 0.05553035 0.06594487
 0.1097468  0.06020738 0.05085592 0.11079482 0.08384402 0.10974212
 0.10100008] entropy 2.5089322382513077
permutation 600 [0.09780715 0.06109601 0.03445109 0.[...]
{'fraction_non_alphanumeric': 0.10139416983523447, 'fraction_numerical': 0.16117448246725813, 'mean_word_length': 4.499419279907085, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '131631', 'license': 'Apache-2.0', 'n_tokens_mistral': 2196, 'n_tokens_neox': 1727, 'n_words': 392, 'path': 'Shapley-CMI valuation.ipynb', 'repo_name': 'wangleye/FedValue', 'size': '4734'}