Initial commit
This commit is contained in:
commit
8542a1f9ef
59 files changed
+73464
No files matched your search
+198
@@ -0,0 +1,198 @@
|
||||
### system related operations
|
||||
import os
|
||||
from inspect import getsource
|
||||
from IPython.display import HTML
|
||||
from IPython.display import display
|
||||
|
||||
|
||||
def psource(*functions):
|
||||
"""Print the source code for the given function(s)."""
|
||||
source_code = '\n\n'.join(getsource(fn) for fn in functions)
|
||||
try:
|
||||
from pygments.formatters import HtmlFormatter
|
||||
from pygments.lexers import PythonLexer
|
||||
from pygments import highlight
|
||||
|
||||
display(HTML(highlight(source_code, PythonLexer(), HtmlFormatter(full=True))))
|
||||
|
||||
except ImportError:
|
||||
print(source_code)
|
||||
|
||||
|
||||
def parse_csv(input, delim=','):
|
||||
r"""
|
||||
Input is a string consisting of lines, each line has comma-delimited
|
||||
fields. Convert this into a list of lists. Blank lines are skipped.
|
||||
Fields that look like numbers are converted to numbers.
|
||||
The delim defaults to ',' but '\t' and None are also reasonable values.
|
||||
>>> parse_csv('1, 2, 3 \n 0, 2, na')
|
||||
[[1, 2, 3], [0, 2, 'na']]
|
||||
"""
|
||||
lines = [line for line in input.splitlines() if line.strip()]
|
||||
return [list(map(num_or_str, line.split(delim))) for line in lines]
|
||||
|
||||
|
||||
def open_data(name, mode='r'):
|
||||
data_root = os.path.dirname(__file__)
|
||||
data_file = os.path.join(data_root, *[os.pardir, 'data', name])
|
||||
|
||||
return open(data_file, mode=mode)
|
||||
|
||||
|
||||
### math and data structure
|
||||
import numpy as np
|
||||
import math
|
||||
from statistics import mean, stdev
|
||||
import random
|
||||
|
||||
|
||||
def normalize(dist):
|
||||
"""Multiply each number by a constant such that the sum is 1.0"""
|
||||
if isinstance(dist, dict):
|
||||
total = sum(dist.values())
|
||||
for key in dist:
|
||||
dist[key] = dist[key] / total
|
||||
assert 0 <= dist[key] <= 1 # probabilities must be between 0 and 1
|
||||
return dist
|
||||
total = sum(dist)
|
||||
return [(n / total) for n in dist]
|
||||
|
||||
|
||||
def random_weights(min_value, max_value, num_weights):
|
||||
return [random.uniform(min_value, max_value) for _ in range(num_weights)]
|
||||
|
||||
|
||||
def sigmoid(x):
|
||||
"""Return activation value of x with sigmoid function."""
|
||||
return 1 / (1 + np.exp(-x))
|
||||
|
||||
|
||||
def sigmoid_derivative(value):
|
||||
return value * (1 - value)
|
||||
|
||||
|
||||
def remove_all(item, seq):
|
||||
"""Return a copy of seq (or string) with all occurrences of item removed."""
|
||||
if isinstance(seq, str):
|
||||
return seq.replace(item, '')
|
||||
elif isinstance(seq, set):
|
||||
rest = seq.copy()
|
||||
rest.remove(item)
|
||||
return rest
|
||||
else:
|
||||
return [x for x in seq if x != item]
|
||||
|
||||
|
||||
def unique(seq):
|
||||
"""Remove duplicate elements from seq. Assumes hashable elements."""
|
||||
return list(set(seq))
|
||||
|
||||
|
||||
def num_or_str(x): # TODO: rename as `atom`
|
||||
"""The argument is a string; convert to a number if
|
||||
possible, or strip it."""
|
||||
try:
|
||||
return int(x)
|
||||
except ValueError:
|
||||
try:
|
||||
return float(x)
|
||||
except ValueError:
|
||||
return str(x).strip()
|
||||
|
||||
|
||||
def euclidean_distance(x, y):
|
||||
return np.sqrt(sum((_x - _y) ** 2 for _x, _y in zip(x, y)))
|
||||
|
||||
|
||||
def manhattan_distance(x, y):
|
||||
return sum(abs(_x - _y) for _x, _y in zip(x, y))
|
||||
|
||||
|
||||
def hamming_distance(x, y):
|
||||
return sum(_x != _y for _x, _y in zip(x, y))
|
||||
|
||||
|
||||
def rms_error(x, y):
|
||||
return np.sqrt(ms_error(x, y))
|
||||
|
||||
|
||||
def ms_error(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))
|
||||
|
||||
|
||||
def mean_boolean_error(x, y):
|
||||
return mean(_x != _y for _x, _y in zip(x, y))
|
||||
|
||||
|
||||
identity = lambda x: x
|
||||
|
||||
|
||||
def argmin_random_tie(seq, key=identity):
|
||||
"""Return a minimum element of seq; break ties at random."""
|
||||
return min(shuffled(seq), key=key)
|
||||
|
||||
|
||||
def argmax_random_tie(seq, key=identity):
|
||||
"""Return an element with highest fn(seq[i]) score; break ties at random."""
|
||||
return max(shuffled(seq), key=key)
|
||||
|
||||
|
||||
def shuffled(iterable):
|
||||
"""Randomly shuffle a copy of iterable."""
|
||||
items = list(iterable)
|
||||
random.shuffle(items)
|
||||
return items
|
||||
|
||||
|
||||
### learner related operations
|
||||
class Activation:
|
||||
|
||||
def function(self, x):
|
||||
return NotImplementedError
|
||||
|
||||
def derivative(self, x):
|
||||
return NotImplementedError
|
||||
|
||||
def __call__(self, x):
|
||||
return self.function(x)
|
||||
|
||||
|
||||
class Sigmoid(Activation):
|
||||
|
||||
def function(self, x):
|
||||
return 1 / (1 + np.exp(-x))
|
||||
|
||||
def derivative(self, value):
|
||||
return value * (1 - value)
|
||||
|
||||
|
||||
def err_ratio(learner, dataset, examples=None):
|
||||
"""
|
||||
Return the proportion of the examples that are NOT correctly predicted.
|
||||
verbose - 0: No output; 1: Output wrong; 2 (or greater): Output correct
|
||||
"""
|
||||
examples = examples or dataset.examples
|
||||
if len(examples) == 0:
|
||||
return 0.0
|
||||
right = 0
|
||||
for example in examples:
|
||||
desired = example[dataset.target]
|
||||
output = learner.predict(dataset.sanitize(example))
|
||||
if output == desired:
|
||||
right += 1
|
||||
return 1 - (right / len(examples))
|
||||
|
||||
|
||||
def grade_learner(learner, tests):
|
||||
"""
|
||||
Grades the given learner based on how many tests it passes.
|
||||
tests is a list with each element in the form: (values, output).
|
||||
"""
|
||||
# for X, y in tests:
|
||||
# print(learner.predict(X), y)
|
||||
return mean([int(learner.predict(X) == y) for X, y in tests])
|
||||
|
||||
Reference in new issue
Block a user