From 0188c8e755e8950facd9eb34932000c2fb0569fa Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Thu, 3 Jul 2014 20:44:02 +0100 Subject: [PATCH] Merged slides from presentation-slides branch --- slides/affine-break.html | 91 ++++++ slides/affine-encipher.html | 236 ++++++++++++++ slides/alternative-plaintext-scoring.html | 244 ++++++++++++++ slides/caesar-break.html | 155 ++++----- slides/fast-good-cheap.gif | Bin 0 -> 9192 bytes slides/further-work.html | 92 ++++++ slides/gcd.svg | 344 ++++++++++++++++++++ slides/keyword-break.html | 224 +++++++++++++ slides/keyword-encipher.html | 209 ++++++++++++ slides/transposition-encipher.html | 258 +++++++++++++++ slides/word-segmentation.html | 370 ++++++++++++++++++++++ 11 files changed, 2147 insertions(+), 76 deletions(-) create mode 100644 slides/affine-break.html create mode 100644 slides/affine-encipher.html create mode 100644 slides/alternative-plaintext-scoring.html create mode 100644 slides/fast-good-cheap.gif create mode 100644 slides/further-work.html create mode 100644 slides/gcd.svg create mode 100644 slides/keyword-break.html create mode 100644 slides/keyword-encipher.html create mode 100644 slides/transposition-encipher.html create mode 100644 slides/word-segmentation.html diff --git a/slides/affine-break.html b/slides/affine-break.html new file mode 100644 index 0000000..58b27f6 --- /dev/null +++ b/slides/affine-break.html @@ -0,0 +1,91 @@ + + + + Affine ciphers + + + + + + + + + + + + diff --git a/slides/affine-encipher.html b/slides/affine-encipher.html new file mode 100644 index 0000000..30f3900 --- /dev/null +++ b/slides/affine-encipher.html @@ -0,0 +1,236 @@ + + + + Affine ciphers + + + + + + + + + + + + diff --git a/slides/alternative-plaintext-scoring.html b/slides/alternative-plaintext-scoring.html new file mode 100644 index 0000000..d6f4aa1 --- /dev/null +++ b/slides/alternative-plaintext-scoring.html @@ -0,0 +1,244 @@ + + + + Alternative plaintext scoring + + + + + + + + + + + + diff --git a/slides/caesar-break.html b/slides/caesar-break.html index 187719d..5ea77b9 100644 --- a/slides/caesar-break.html +++ b/slides/caesar-break.html @@ -111,11 +111,34 @@ e | 756288 . | . z | 3575 -One way of thinking about this is a 26-dimensional vector. +Use this to predict the probability of each letter, and hence the probability of a sequence of letters. -Create a vector of our text, and one of idealised English. +--- + +# An infinite number of monkeys + +What is the probability that this string of letters is a sample of English? + +## Naive Bayes, or the bag of letters + +Ignore letter order, just treat each letter individually. + +Probability of a text is `\( \prod_i p_i \)` + +Letter | h | e | l | l | o | hello +------------|---------|---------|---------|---------|---------|------- +Probability | 0.06645 | 0.12099 | 0.04134 | 0.04134 | 0.08052 | 1.10648239 × 10-6 + +Letter | i | f | m | m | p | ifmmp +------------|---------|---------|---------|---------|---------|------- +Probability | 0.06723 | 0.02159 | 0.02748 | 0.02748 | 0.01607 | 1.76244520 × 10-8 + +(Implmentation issue: this can often underflow, so get in the habit of rephrasing it as `\( \sum_i \log p_i \)`) + +Letter | h | e | l | l | o | hello +------------|---------|---------|---------|---------|---------|------- +Probability | -1.1774 | -0.9172 | -1.3836 | -1.3836 | -1.0940 | -5.956055 -The distance between the vectors is how far from English the text is. --- @@ -126,13 +149,15 @@ But before then how do we count the letters? * Read a file into a string ```python open() -read() +.read() ``` * Count them ```python import collections ``` +Create the `language_models.py` file for this. + --- # Canonical forms @@ -146,20 +171,21 @@ Counting letters in _War and Peace_ gives all manner of junk. ``` --- - # Accents ```python ->>> caesar_encipher_letter('é', 1) +>>> 'é' in string.ascii_letters +>>> 'e' in string.ascii_letters ``` -What does it produce? - -What should it produce? ## Unicode, combining codepoints, and normal forms Text encodings will bite you when you least expect it. +- **é** : LATIN SMALL LETTER E WITH ACUTE (U+00E9) + +- **e** + ** ́** : LATIN SMALL LETTER E (U+0065) + COMBINING ACUTE ACCENT (U+0301) + * urlencoding is the other pain point. --- @@ -190,101 +216,78 @@ def unaccent(text): --- -# Vector distances - -.float-right[![right-aligned Vector subtraction](vector-subtraction.svg)] - -Several different distance measures (__metrics__, also called __norms__): +# Find the frequencies of letters in English -* L2 norm (Euclidean distance): -`\(\|\mathbf{a} - \mathbf{b}\| = \sqrt{\sum_i (\mathbf{a}_i - \mathbf{b}_i)^2} \)` +1. Read from `shakespeare.txt`, `sherlock-holmes.txt`, and `war-and-peace.txt`. +2. Find the frequencies (`.update()`) +3. Sort by count +4. Write counts to `count_1l.txt` (`'text{}\n'.format()`) -* L1 norm (Manhattan distance, taxicab distance): -`\(\|\mathbf{a} - \mathbf{b}\| = \sum_i |\mathbf{a}_i - \mathbf{b}_i| \)` +--- -* L3 norm: -`\(\|\mathbf{a} - \mathbf{b}\| = \sqrt[3]{\sum_i |\mathbf{a}_i - \mathbf{b}_i|^3} \)` +# Reading letter probabilities -The higher the power used, the more weight is given to the largest differences in components. +1. Load the file `count_1l.txt` into a dict, with letters as keys. -(Extends out to: +2. Normalise the counts (components of vector sum to 1): `$$ \hat{\mathbf{x}} = \frac{\mathbf{x}}{\| \mathbf{x} \|} = \frac{\mathbf{x}}{ \mathbf{x}_1 + \mathbf{x}_2 + \mathbf{x}_3 + \dots }$$` + * Return a new dict + * Remember the doctest! -* L0 norm (Hamming distance): -`$$\|\mathbf{a} - \mathbf{b}\| = \sum_i \left\{ -\begin{matrix} 1 &\mbox{if}\ \mathbf{a}_i \neq \mathbf{b}_i , \\ - 0 &\mbox{if}\ \mathbf{a}_i = \mathbf{b}_i \end{matrix} \right. $$` +3. Create a dict `Pl` that gives the log probability of a letter -* L norm: -`\(\|\mathbf{a} - \mathbf{b}\| = \max_i{(\mathbf{a}_i - \mathbf{b}_i)} \)` +4. Create a function `Pletters` that gives the probability of an iterable of letters + * What preconditions should this function have? + * Remember the doctest! -neither of which will be that useful.) --- -# Normalisation of vectors +# Breaking caesar ciphers -Frequency distributions drawn from different sources will have different lengths. For a fair comparison we need to scale them. +## Remember the basic idea -* Eucliean scaling (vector with unit length): `$$ \hat{\mathbf{x}} = \frac{\mathbf{x}}{\| \mathbf{x} \|} = \frac{\mathbf{x}}{ \sqrt{\mathbf{x}_1^2 + \mathbf{x}_2^2 + \mathbf{x}_3^2 + \dots } }$$` +``` +for each key: + decipher with this key + how close is it to English? + remember the best key +``` -* Normalisation (components of vector sum to 1): `$$ \hat{\mathbf{x}} = \frac{\mathbf{x}}{\| \mathbf{x} \|} = \frac{\mathbf{x}}{ \mathbf{x}_1 + \mathbf{x}_2 + \mathbf{x}_3 + \dots }$$` +Try it on the text in `2013/1a.ciphertext`. Does it work? --- -# Angle, not distance - -Rather than looking at the distance between the vectors, look at the angle between them. - -.float-right[![right-aligned Vector dot product](vector-dot-product.svg)] +# Aside: Logging -Vector dot product shows how much of one vector lies in the direction of another: -`\( \mathbf{A} \bullet \mathbf{B} = -\| \mathbf{A} \| \cdot \| \mathbf{B} \| \cos{\theta} \)` - -But, -`\( \mathbf{A} \bullet \mathbf{B} = \sum_i \mathbf{A}_i \cdot \mathbf{B}_i \)` -and `\( \| \mathbf{A} \| = \sum_i \mathbf{A}_i^2 \)` - -A bit of rearranging give the cosine simiarity: -`$$ \cos{\theta} = \frac{ \mathbf{A} \bullet \mathbf{B} }{ \| \mathbf{A} \| \cdot \| \mathbf{B} \| } = -\frac{\sum_i \mathbf{A}_i \cdot \mathbf{B}_i}{\sum_i \mathbf{A}_i^2 \times \sum_i \mathbf{B}_i^2} $$` - -This is independent of vector lengths! - -Cosine similarity is 1 if in parallel, 0 if perpendicular, -1 if antiparallel. - ---- +Better than scattering `print()`statements through your code -# An infinite number of monkeys - -What is the probability that this string of letters is a sample of English? +```python +import logging -Given 'th', 'e' is about six times more likely than 'a' or 'i'. +logger = logging.getLogger(__name__) +logger.addHandler(logging.FileHandler('cipher.log')) +logger.setLevel(logging.WARNING) -## Naive Bayes, or the bag of letters + logger.debug('Caesar break attempt using key {0} gives fit of {1} ' + 'and decrypt starting: {2}'.format(shift, fit, plaintext[:50])) -Ignore letter order, just treat each letter individually. +``` +* Yes, it's ugly. -Probability of a text is `\( \prod_i p_i \)` +Use `logger.setLevel()` to change the level: CRITICAL, ERROR, WARNING, INFO, DEBUG -(Implmentation issue: this can often underflow, so get in the habit of rephrasing it as `\( \sum_i \log p_i \)`) +Use `logger.debug()`, `logger.info()`, etc. to log a message. --- -# Which is best? - - | Euclidean | Normalised ----|-----------|------------ -L1 | x | x -L2 | x | x -L3 | x | x -Cosine | x | x - -And the probability measure! - -* Nine different ways of measuring fitness. +# How much ciphertext do we need? -## Computing is an empircal science +## Let's do an experiment to find out +1. Load the whole corpus into a string (sanitised) +2. Select a random chunk of plaintext and a random key +3. Encipher the text +4. Score 1 point if `caesar_cipher_break()` recovers the correct key +5. Repeat many times and with many plaintext lengths diff --git a/slides/fast-good-cheap.gif b/slides/fast-good-cheap.gif new file mode 100644 index 0000000000000000000000000000000000000000..63411f0ee1c3ebeb00ab49d30edccb436715e0c0 GIT binary patch literal 9192 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 yS`{#z)LEU@d7apqo!Ysb+}WMp`JLbyp5i&4 + + + Breaking keyword ciphers + + + + + + + + + + + + + diff --git a/slides/gcd.svg b/slides/gcd.svg new file mode 100644 index 0000000..80f8256 --- /dev/null +++ b/slides/gcd.svg @@ -0,0 +1,344 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/slides/keyword-break.html b/slides/keyword-break.html new file mode 100644 index 0000000..49160bb --- /dev/null +++ b/slides/keyword-break.html @@ -0,0 +1,224 @@ + + + + Breaking keyword ciphers + + + + + + + + + + + + diff --git a/slides/keyword-encipher.html b/slides/keyword-encipher.html new file mode 100644 index 0000000..168bb5f --- /dev/null +++ b/slides/keyword-encipher.html @@ -0,0 +1,209 @@ + + + + Keyword ciphers + + + + + + + + + + + + diff --git a/slides/transposition-encipher.html b/slides/transposition-encipher.html new file mode 100644 index 0000000..0c09a4b --- /dev/null +++ b/slides/transposition-encipher.html @@ -0,0 +1,258 @@ + + + + Keyword ciphers + + + + + + + + + + + + diff --git a/slides/word-segmentation.html b/slides/word-segmentation.html new file mode 100644 index 0000000..16fcb0a --- /dev/null +++ b/slides/word-segmentation.html @@ -0,0 +1,370 @@ + + + + Word segmentation + + + + + + + + + + + + + -- 2.34.1