From 7b171182f99331c27239cfca2e9530d66e6348d2 Mon Sep 17 00:00:00 2001 From: Rahul Goswami Date: Fri, 9 Mar 2018 20:15:19 +0530 Subject: [PATCH 1/5] styling changes and bug fixes in learning.py --- learning.py | 126 ++++++++++++++++++++++++++++------------------------ 1 file changed, 69 insertions(+), 57 deletions(-) diff --git a/learning.py b/learning.py index a231e8a78..dc9cfa112 100644 --- a/learning.py +++ b/learning.py @@ -19,7 +19,7 @@ def euclidean_distance(X, Y): - return math.sqrt(sum([(x - y)**2 for x, y in zip(X, Y)])) + return math.sqrt(sum((x - y)**2 for x, y in zip(X, Y))) def rms_error(X, Y): @@ -27,15 +27,15 @@ def rms_error(X, Y): def ms_error(X, Y): - return mean([(x - y)**2 for x, y in zip(X, Y)]) + return mean((x - y)**2 for x, y in zip(X, Y)) def mean_error(X, Y): - return mean([abs(x - y) for x, y in zip(X, Y)]) + return mean(abs(x - y) for x, y in zip(X, Y)) def manhattan_distance(X, Y): - return sum([abs(x - y) for x, y in zip(X, Y)]) + return sum(abs(x - y) for x, y in zip(X, Y)) def mean_boolean_error(X, Y): @@ -86,22 +86,20 @@ def __init__(self, examples=None, attrs=None, attrnames=None, target=-1, self.source = source self.values = values self.distance = distance - if values is None: - self.got_values_flag = False - else: - self.got_values_flag = True - + self.got_values_flag = bool(values) + # Initialize .examples from string or list or data directory if isinstance(examples, str): self.examples = parse_csv(examples) - elif examples is None: - self.examples = parse_csv(open_data(name + '.csv').read()) else: - self.examples = examples + self.examples = examples or parse_csv(open_data(name + '.csv').read()) + # Attrs are the indices of examples, unless otherwise stated. - if attrs is None and self.examples is not None: + if self.examples and not attrs: attrs = list(range(len(self.examples[0]))) + self.attrs = attrs + # Initialize .attrnames from string, list, or by default if isinstance(attrnames, str): self.attrnames = attrnames.split() @@ -201,14 +199,15 @@ def find_means_and_deviations(self): item_buckets = self.split_values_by_classes() - means = defaultdict(lambda: [0 for i in range(feature_numbers)]) - deviations = defaultdict(lambda: [0 for i in range(feature_numbers)]) + means = defaultdict(lambda: [0] * feature_numbers) + deviations = defaultdict(lambda: [0] * feature_numbers) for t in target_names: # Find all the item feature values for item in class t features = [[] for i in range(feature_numbers)] for item in item_buckets[t]: - features = [features[i] + [item[i]] for i in range(feature_numbers)] + for i in range(feature_numbers): + features[i].append(item[i]) # Calculate means and deviations fo the class for i in range(feature_numbers): @@ -245,12 +244,14 @@ class CountingProbDist: p.sample() returns a random element from the distribution. p[o] returns the probability for o (as in a regular ProbDist).""" - def __init__(self, observations=[], default=0): + def __init__(self, observations=None, default=0): """Create a distribution, and optionally add in some observations. By default this is an unsmoothed distribution, but saying default=1, for example, gives you add-one smoothing.""" + if observations is None: + observations = [] self.dictionary = {} - self.n_obs = 0.0 + self.n_obs = 0 self.default = default self.sampler = None @@ -400,10 +401,10 @@ def predict(example): def truncated_svd(X, num_val=2, max_iter=1000): - """Computes the first component of SVD""" + """Compute the first component of SVD.""" - def normalize_vec(X, n = 2): - """Normalizes two parts (:m and m:) of the vector""" + def normalize_vec(X, n=2): + """Normalize two parts (:m and m:) of the vector.""" X_m = X[:m] X_n = X[m:] norm_X_m = norm(X_m, n) @@ -413,7 +414,7 @@ def normalize_vec(X, n = 2): return Y_m + Y_n def remove_component(X): - """Removes components of already obtained eigen vectors from X""" + """Remove components of already obtained eigen vectors from X.""" X_m = X[:m] X_n = X[m:] for eivec in eivec_m: @@ -425,21 +426,21 @@ def remove_component(X): return X_m + X_n m, n = len(X), len(X[0]) - A = [[0 for _ in range(n + m)] for _ in range(n + m)] + A = [[0]*(n+m) for _ in range(n+m)] for i in range(m): for j in range(n): - A[i][m + j] = A[m + j][i] = X[i][j] + A[i][m+j] = A[m+j][i] = X[i][j] eivec_m = [] eivec_n = [] eivals = [] for _ in range(num_val): - X = [random.random() for _ in range(m + n)] + X = [random.random() for _ in range(m+n)] X = remove_component(X) X = normalize_vec(X) - for _ in range(max_iter): + for i in range(max_iter): old_X = X X = matrix_multiplication(A, [[x] for x in X]) X = [x[0] for x in X] @@ -489,6 +490,7 @@ def display(self, indent=0): for (val, subtree) in self.branches.items(): print(' ' * 4 * indent, name, '=', val, '==>', end=' ') subtree.display(indent + 1) + print() # newline def __repr__(self): return ('DecisionFork({0!r}, {1!r}, {2!r})' @@ -560,8 +562,8 @@ def information_gain(attr, examples): def I(examples): return information_content([count(target, v, examples) for v in values[target]]) - N = float(len(examples)) - remainder = sum((len(examples_i) / N) * I(examples_i) + N = len(examples) + remainder = sum((len(examples_i)/N) * I(examples_i) for (v, examples_i) in split_by(attr, examples)) return I(examples) - remainder @@ -643,7 +645,7 @@ def predict(example): # ______________________________________________________________________________ -def NeuralNetLearner(dataset, hidden_layer_sizes=[3], +def NeuralNetLearner(dataset, hidden_layer_sizes=None, learning_rate=0.01, epochs=100): """Layered feed-forward network. hidden_layer_sizes: List of number of hidden units per hidden layer @@ -651,6 +653,7 @@ def NeuralNetLearner(dataset, hidden_layer_sizes=[3], epochs: Number of passes over the dataset """ + hidden_layer_sizes = hidden_layer_sizes or [3] # default value i_units = len(dataset.inputs) o_units = len(dataset.values[dataset.target]) @@ -684,7 +687,7 @@ def predict(example): def random_weights(min_value, max_value, num_weights): - return [random.uniform(min_value, max_value) for i in range(num_weights)] + return [random.uniform(min_value, max_value) for _ in range(num_weights)] def BackPropagationLearner(dataset, net, learning_rate, epochs): @@ -699,7 +702,7 @@ def BackPropagationLearner(dataset, net, learning_rate, epochs): ''' As of now dataset.target gives an int instead of list, Changing dataset class will have effect on all the learners. - Will be taken care of later + Will be taken care of later. ''' o_nodes = net[-1] i_nodes = net[0] @@ -728,12 +731,13 @@ def BackPropagationLearner(dataset, net, learning_rate, epochs): node.value = node.activation(in_val) # Initialize delta - delta = [[] for i in range(n_layers)] + delta = [[] for _ in range(n_layers)] # Compute outer layer delta # Error for the MSE cost function err = [t_val[i] - o_nodes[i].value for i in range(o_units)] + # The activation function used is the sigmoid function delta[-1] = [sigmoid_derivative(o_nodes[i].value) * err[i] for i in range(o_units)] @@ -743,6 +747,7 @@ def BackPropagationLearner(dataset, net, learning_rate, epochs): layer = net[i] h_units = len(layer) nx_layer = net[i+1] + # weights from each ith layer node to each i + 1th layer node w = [[node.weights[k] for node in nx_layer] for k in range(h_units)] @@ -791,8 +796,8 @@ class NNUnit: """ def __init__(self, weights=None, inputs=None): - self.weights = [] - self.inputs = [] + self.weights = weights or [] + self.inputs = inputs or [] self.value = None self.activation = sigmoid @@ -827,6 +832,7 @@ def init_examples(examples, idx_i, idx_t, o_units): for i in range(len(examples)): e = examples[i] + # Input values of e inputs[i] = [e[i] for i in idx_i] @@ -902,24 +908,26 @@ def predict(example): def AdaBoost(L, K): """[Figure 18.34]""" + def train(dataset): examples, target = dataset.examples, dataset.target N = len(examples) - epsilon = 1. / (2 * N) - w = [1. / N] * N + epsilon = 1/(2*N) + w = [1/N]*N h, z = [], [] for k in range(K): h_k = L(dataset, w) h.append(h_k) error = sum(weight for example, weight in zip(examples, w) if example[target] != h_k(example)) + # Avoid divide-by-0 from either 0% or 100% error rates: error = clip(error, epsilon, 1 - epsilon) for j, example in enumerate(examples): if example[target] == h_k(example): - w[j] *= error / (1. - error) + w[j] *= error/(1 - error) w = normalize(w) - z.append(math.log((1. - error) / error)) + z.append(math.log((1 - error)/error)) return WeightedMajority(h, z) return train @@ -934,13 +942,13 @@ def predict(example): def weighted_mode(values, weights): """Return the value with the greatest total weight. - >>> weighted_mode('abbaa', [1,2,3,1,2]) + >>> weighted_mode('abbaa', [1, 2, 3, 1, 2]) 'b' """ totals = defaultdict(int) for v, w in zip(values, weights): totals[v] += w - return max(list(totals.keys()), key=totals.get) + return max(totals, key=totals.__getitem__) # _____________________________________________________________________________ # Adapting an unweighted learner for AdaBoost @@ -966,14 +974,14 @@ def weighted_replicate(seq, weights, n): """Return n selections from seq, with the count of each element of seq proportional to the corresponding weight (filling in fractions randomly). - >>> weighted_replicate('ABC', [1,2,1], 4) + >>> weighted_replicate('ABC', [1, 2, 1], 4) ['A', 'B', 'B', 'C'] """ assert len(seq) == len(weights) weights = normalize(weights) - wholes = [int(w * n) for w in weights] - fractions = [(w * n) % 1 for w in weights] - return (flatten([x] * nx for x, nx in zip(seq, wholes)) + + wholes = [int(w*n) for w in weights] + fractions = [(w*n) % 1 for w in weights] + return (flatten([x]*nx for x, nx in zip(seq, wholes)) + weighted_sample_with_replacement(n - sum(wholes), seq, fractions)) @@ -986,11 +994,10 @@ def flatten(seqs): return sum(seqs, []) def err_ratio(predict, dataset, examples=None, verbose=0): """Return the proportion of the examples that are NOT correctly predicted. verbose - 0: No output; 1: Output wrong; 2 (or greater): Output correct""" - if examples is None: - examples = dataset.examples + examples = examples or dataset.examples if len(examples) == 0: return 0.0 - right = 0.0 + right = 0 for example in examples: desired = example[dataset.target] output = predict(dataset.sanitize(example)) @@ -1001,7 +1008,7 @@ def err_ratio(predict, dataset, examples=None, verbose=0): elif verbose: print('WRONG: got {}, expected {} for {}'.format( output, desired, example)) - return 1 - (right / len(examples)) + return 1 - (right/len(examples)) def grade_learner(predict, tests): @@ -1025,8 +1032,7 @@ def cross_validation(learner, size, dataset, k=10, trials=1): That is, keep out 1/k of the examples for testing on each of k runs. Shuffle the examples first; if trials>1, average over several shuffles. Returns Training error, Validataion error""" - if k is None: - k = len(dataset.examples) + k = k or len(dataset.examples) if trials > 1: trial_errT = 0 trial_errV = 0 @@ -1035,7 +1041,7 @@ def cross_validation(learner, size, dataset, k=10, trials=1): k=10, trials=1) trial_errT += errT trial_errV += errV - return trial_errT / trials, trial_errV / trials + return trial_errT/trials, trial_errV/trials else: fold_errT = 0 fold_errV = 0 @@ -1049,9 +1055,10 @@ def cross_validation(learner, size, dataset, k=10, trials=1): h = learner(dataset, size) fold_errT += err_ratio(h, dataset, train_data) fold_errV += err_ratio(h, dataset, val_data) + # Reverting back to original once test is completed dataset.examples = examples - return fold_errT / k, fold_errV / k + return fold_errT/k, fold_errV/k def cross_validation_wrapper(learner, dataset, k=10, trials=1): @@ -1073,7 +1080,7 @@ def cross_validation_wrapper(learner, dataset, k=10, trials=1): min_val = math.inf i = 0 - while i Date: Sat, 10 Mar 2018 00:16:57 +0530 Subject: [PATCH 2/5] Fix #833 and other pep corrections in mdp.py --- mdp.py | 84 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/mdp.py b/mdp.py index 9dcbd781a..b24e8e15e 100644 --- a/mdp.py +++ b/mdp.py @@ -2,8 +2,8 @@ First we define an MDP, and the special case of a GridMDP, in which states are laid out in a 2-dimensional grid. We also represent a policy -as a dictionary of {state:action} pairs, and a Utility function as a -dictionary of {state:number} pairs. We then define the value_iteration +as a dictionary of {state: action} pairs, and a Utility function as a +dictionary of {state: number} pairs. We then define the value_iteration and policy_iteration algorithms.""" from utils import argmax, vector_add, orientations, turn_right, turn_left @@ -21,36 +21,33 @@ class MDP: list of (p, s') pairs. We also keep track of the possible states, terminal states, and actions for each state. [page 646]""" - def __init__(self, init, actlist, terminals, transitions = {}, reward = None, states=None, gamma=.9): + def __init__(self, init, actlist, terminals, transitions=None, reward=None, states=None, gamma=0.9): if not (0 < gamma <= 1): raise ValueError("An MDP must have 0 < gamma <= 1") - if states: - self.states = states - else: - ## collect states from transitions table - self.states = self.get_states_from_transitions(transitions) + # collect states from transitions table if not passed. + self.states = states or self.get_states_from_transitions(transitions) - self.init = init if isinstance(actlist, list): - ## if actlist is a list, all states have the same actions + # if actlist is a list, all states have the same actions self.actlist = actlist + elif isinstance(actlist, dict): - ## if actlist is a dict, different actions for each state + # if actlist is a dict, different actions for each state self.actlist = actlist self.terminals = terminals - self.transitions = transitions - if self.transitions == {}: + self.transitions = transitions or {} + if not self.transitions: print("Warning: Transition table is empty.") + self.gamma = gamma - if reward: - self.reward = reward - else: - self.reward = {s : 0 for s in self.states} - #self.check_consistency() + + self.reward = reward or {s: 0 for s in self.states} + + # self.check_consistency() def R(self, state): """Return a numeric reward for this state.""" @@ -59,13 +56,13 @@ def R(self, state): def T(self, state, action): """Transition model. From a state and an action, return a list of (probability, result-state) pairs.""" - if(self.transitions == {}): + if not self.transitions: raise ValueError("Transition model is missing") else: return self.transitions[state][action] def actions(self, state): - """Set of actions that can be performed in this state. By default, a + """Return a set of actions that can be performed in this state. By default, a fixed list of actions, except for terminal states. Override this method if you need to specialize by state.""" if state in self.terminals: @@ -76,23 +73,28 @@ def actions(self, state): def get_states_from_transitions(self, transitions): if isinstance(transitions, dict): s1 = set(transitions.keys()) - s2 = set([tr[1] for actions in transitions.values() - for effects in actions.values() for tr in effects]) + s2 = set(tr[1] for actions in transitions.values() + for effects in actions.values() + for tr in effects) return s1.union(s2) else: print('Could not retrieve states from transitions') return None def check_consistency(self): + # check that all states in transitions are valid assert set(self.states) == self.get_states_from_transitions(self.transitions) + # check that init is a valid state assert self.init in self.states + # check reward for each state - #assert set(self.reward.keys()) == set(self.states) assert set(self.reward.keys()) == set(self.states) + # check that all terminals are valid states - assert all([t in self.states for t in self.terminals]) + assert all(t in self.states for t in self.terminals) + # check that probability distributions for all actions sum to 1 for s1, actions in self.transitions.items(): for a in actions.keys(): @@ -110,7 +112,7 @@ class GridMDP(MDP): An action is an (x, y) unit vector; e.g. (1, 0) means move east.""" def __init__(self, grid, terminals, init=(0, 0), gamma=.9): - grid.reverse() # because we want row 0 on bottom, not on top + grid.reverse() # because we want row 0 on bottom, not on top reward = {} states = set() self.rows = len(grid) @@ -118,7 +120,7 @@ def __init__(self, grid, terminals, init=(0, 0), gamma=.9): self.grid = grid for x in range(self.cols): for y in range(self.rows): - if grid[y][x] is not None: + if grid[y][x]: states.add((x, y)) reward[(x, y)] = grid[y][x] self.states = states @@ -129,22 +131,19 @@ def __init__(self, grid, terminals, init=(0, 0), gamma=.9): for a in actlist: transitions[s][a] = self.calculate_T(s, a) MDP.__init__(self, init, actlist=actlist, - terminals=terminals, transitions = transitions, - reward = reward, states = states, gamma=gamma) + terminals=terminals, transitions=transitions, + reward=reward, states=states, gamma=gamma) def calculate_T(self, state, action): - if action is None: - return [(0.0, state)] - else: + if action: return [(0.8, self.go(state, action)), (0.1, self.go(state, turn_right(action))), (0.1, self.go(state, turn_left(action)))] + else: + return [(0.0, state)] def T(self, state, action): - if action is None: - return [(0.0, state)] - else: - return self.transitions[state][action] + return self.transitions[state][action] if action else [(0.0, state)] def go(self, state, direction): """Return the state that results from going in this direction.""" @@ -158,8 +157,7 @@ def to_grid(self, mapping): for y in range(self.rows)])) def to_arrows(self, policy): - chars = { - (1, 0): '>', (0, 1): '^', (-1, 0): '<', (0, -1): 'v', None: '.'} + chars = {(1, 0): '>', (0, 1): '^', (-1, 0): '<', (0, -1): 'v', None: '.'} return self.to_grid({s: chars[a] for (s, a) in policy.items()}) # ______________________________________________________________________________ @@ -185,10 +183,10 @@ def value_iteration(mdp, epsilon=0.001): U = U1.copy() delta = 0 for s in mdp.states: - U1[s] = R(s) + gamma * max([sum([p * U[s1] for (p, s1) in T(s, a)]) - for a in mdp.actions(s)]) + U1[s] = R(s) + gamma * max(sum(p*U[s1] for (p, s1) in T(s, a)) + for a in mdp.actions(s)) delta = max(delta, abs(U1[s] - U[s])) - if delta < epsilon * (1 - gamma) / gamma: + if delta < epsilon*(1 - gamma)/gamma: return U @@ -203,7 +201,7 @@ def best_policy(mdp, U): def expected_utility(a, s, U, mdp): """The expected utility of doing a in state s, according to the MDP and U.""" - return sum([p * U[s1] for (p, s1) in mdp.T(s, a)]) + return sum(p*U[s1] for (p, s1) in mdp.T(s, a)) # ______________________________________________________________________________ @@ -230,7 +228,7 @@ def policy_evaluation(pi, U, mdp, k=20): R, T, gamma = mdp.R, mdp.T, mdp.gamma for i in range(k): for s in mdp.states: - U[s] = R(s) + gamma * sum([p * U[s1] for (p, s1) in T(s, pi[s])]) + U[s] = R(s) + gamma*sum(p*U[s1] for (p, s1) in T(s, pi[s])) return U @@ -267,4 +265,4 @@ def policy_evaluation(pi, U, mdp, k=20): 'plan3' : [(0.1, 'a'), (0.3, 'b'), (0.1, 'c'), (0.5, 'd')], }, } -""" \ No newline at end of file +""" From 11c0c7511bd05e38d6b1fe5669111ef7a5d9fc83 Mon Sep 17 00:00:00 2001 From: Rahul Goswami Date: Sat, 10 Mar 2018 00:25:44 +0530 Subject: [PATCH 3/5] minor change mdp.py --- mdp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mdp.py b/mdp.py index b24e8e15e..738ae130b 100644 --- a/mdp.py +++ b/mdp.py @@ -62,7 +62,7 @@ def T(self, state, action): return self.transitions[state][action] def actions(self, state): - """Return a set of actions that can be performed in this state. By default, a + """Return a list of actions that can be performed in this state. By default, a fixed list of actions, except for terminal states. Override this method if you need to specialize by state.""" if state in self.terminals: From 4634c86e9eb4751afdd7de75b8ae11e00c3901fc Mon Sep 17 00:00:00 2001 From: Rahul Goswami Date: Sat, 10 Mar 2018 01:32:30 +0530 Subject: [PATCH 4/5] renamed train_and_test() to train_test_split() #55 #830 --- learning.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/learning.py b/learning.py index dc9cfa112..9ad83d4ac 100644 --- a/learning.py +++ b/learning.py @@ -87,19 +87,19 @@ def __init__(self, examples=None, attrs=None, attrnames=None, target=-1, self.values = values self.distance = distance self.got_values_flag = bool(values) - + # Initialize .examples from string or list or data directory if isinstance(examples, str): self.examples = parse_csv(examples) else: self.examples = examples or parse_csv(open_data(name + '.csv').read()) - + # Attrs are the indices of examples, unless otherwise stated. if self.examples and not attrs: attrs = list(range(len(self.examples[0]))) - + self.attrs = attrs - + # Initialize .attrnames from string, list, or by default if isinstance(attrnames, str): self.attrnames = attrnames.split() @@ -206,8 +206,7 @@ def find_means_and_deviations(self): # Find all the item feature values for item in class t features = [[] for i in range(feature_numbers)] for item in item_buckets[t]: - for i in range(feature_numbers): - features[i].append(item[i]) + features = [features[i].append(item[i]) for i in range(feature_numbers)] # Calculate means and deviations fo the class for i in range(feature_numbers): @@ -1017,7 +1016,7 @@ def grade_learner(predict, tests): return mean(int(predict(X) == y) for X, y in tests) -def train_and_test(dataset, start, end): +def train_test_split(dataset, start, end): """Reserve dataset.examples[start:end] for test; train on the remainder.""" start = int(start) end = int(end) @@ -1049,8 +1048,8 @@ def cross_validation(learner, size, dataset, k=10, trials=1): examples = dataset.examples for fold in range(k): random.shuffle(dataset.examples) - train_data, val_data = train_and_test(dataset, fold * (n / k), - (fold + 1) * (n / k)) + train_data, val_data = train_test_split(dataset, fold * (n / k), + (fold + 1) * (n / k)) dataset.examples = train_data h = learner(dataset, size) fold_errT += err_ratio(h, dataset, train_data) @@ -1060,7 +1059,7 @@ def cross_validation(learner, size, dataset, k=10, trials=1): dataset.examples = examples return fold_errT/k, fold_errV/k - +# TODO: The function cross_validation_wrapper need to be fixed.(The while loop runs forever!) def cross_validation_wrapper(learner, dataset, k=10, trials=1): """[Fig 18.8] Return the optimal value of size having minimum error @@ -1096,14 +1095,14 @@ def leave_one_out(learner, dataset, size=None): """Leave one out cross-validation over the dataset.""" return cross_validation(learner, size, dataset, k=len(dataset.examples)) - +# TODO learningcurve needs to fixed def learningcurve(learner, dataset, trials=10, sizes=None): if sizes is None: sizes = list(range(2, len(dataset.examples) - 10, 2)) def score(learner, size): random.shuffle(dataset.examples) - return train_and_test(learner, dataset, 0, size) + return train_test_split(learner, dataset, 0, size) return [(size, mean([score(learner, size) for t in range(trials)])) for size in sizes] @@ -1229,7 +1228,7 @@ def compare(algorithms=None, datasets = datasets or [iris, orings, zoo, restaurant, SyntheticRestaurant(20), # default list Majority(7, 100), Parity(7, 100), Xor(100)] # of datasets - + print_table([[a.__name__.replace('Learner', '')] + [cross_validation(a, d, k, trials) for d in datasets] for a in algorithms], From b4872cb44b42805f396ec5cea0f9818218f9b57c Mon Sep 17 00:00:00 2001 From: Rahul Goswami Date: Sat, 10 Mar 2018 01:51:32 +0530 Subject: [PATCH 5/5] typo fix --- learning.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/learning.py b/learning.py index 9ad83d4ac..32cf73d81 100644 --- a/learning.py +++ b/learning.py @@ -206,7 +206,8 @@ def find_means_and_deviations(self): # Find all the item feature values for item in class t features = [[] for i in range(feature_numbers)] for item in item_buckets[t]: - features = [features[i].append(item[i]) for i in range(feature_numbers)] + for i in range(feature_numbers): + features[i].append(item[i]) # Calculate means and deviations fo the class for i in range(feature_numbers): @@ -1059,7 +1060,7 @@ def cross_validation(learner, size, dataset, k=10, trials=1): dataset.examples = examples return fold_errT/k, fold_errV/k -# TODO: The function cross_validation_wrapper need to be fixed.(The while loop runs forever!) +# TODO: The function cross_validation_wrapper needs to be fixed. (The while loop runs forever!) def cross_validation_wrapper(learner, dataset, k=10, trials=1): """[Fig 18.8] Return the optimal value of size having minimum error