In this notebook, we'll build a character-wise RNN trained on Anna Karenina, one of my all-time favorite books. It'll be able to generate new text based on the text from the book.
This network is based off of Andrej Karpathy's post on RNNs and implementation in Torch. Also, some information here at r2rt and from Sherjil Ozair on GitHub. Below is the general architecture of the character-wise RNN.
import time
from collections import namedtuple
import numpy as np
import tensorflow as tf
First we'll load the text file and convert it into integers for our network to use. Here I'm creating a couple dictionaries to convert the characters to and from integers. Encoding the characters as integers makes it easier to use as input in the network.
with open('anna.txt', 'r') as f:
text=f.read()
vocab = sorted(set(text))
vocab_to_int = {c: i for i, c in enumerate(vocab)}
int_to_vocab = dict(enumerate(vocab))
encoded = np.array([vocab_to_int[c] for c in text], dtype=np.int32)
Let's check out the first 100 characters, make sure everything is peachy. According to the American Book Review, this is the 6th best first line of a book ever.
text[:100]
'Chapter 1\n\n\nHappy families are all alike; every unhappy family is unhappy in its own\nway.\n\nEverythin'
And we can see the characters encoded as integers.
encoded[:100]
array([31, 64, 57, 72, 76, 61, 74, 1, 16, 0, 0, 0, 36, 57, 72, 72, 81, 1, 62, 57, 69, 65, 68, 65, 61, 75, 1, 57, 74, 61, 1, 57, 68, 68, 1, 57, 68, 65, 67, 61, 26, 1, 61, 78, 61, 74, 81, 1, 77, 70, 64, 57, 72, 72, 81, 1, 62, 57, 69, 65, 68, 81, 1, 65, 75, 1, 77, 70, 64, 57, 72, 72, 81, 1, 65, 70, 1, 65, 76, 75, 1, 71, 79, 70, 0, 79, 57, 81, 13, 0, 0, 33, 78, 61, 74, 81, 76, 64, 65, 70], dtype=int32)
Since the network is working with individual characters, it's similar to a classification problem in which we are trying to predict the next character from the previous text. Here's how many 'classes' our network has to pick from.
len(vocab)
83
Here is where we'll make our mini-batches for training. Remember that we want our batches to be multiple sequences of some desired number of sequence steps. Considering a simple example, our batches would look like this:
We have our text encoded as integers as one long array in encoded
. Let's create a function that will give us an iterator for our batches. I like using generator functions to do this. Then we can pass encoded
into this function and get our batch generator.
The first thing we need to do is discard some of the text so we only have completely full batches. Each batch contains $N \times M$ characters, where $N$ is the batch size (the number of sequences) and $M$ is the number of steps. Then, to get the number of batches we can make from some array arr
, you divide the length of arr
by the batch size. Once you know the number of batches and the batch size, you can get the total number of characters to keep.
After that, we need to split arr
into $N$ sequences. You can do this using arr.reshape(size)
where size
is a tuple containing the dimensions sizes of the reshaped array. We know we want $N$ sequences (n_seqs
below), let's make that the size of the first dimension. For the second dimension, you can use -1
as a placeholder in the size, it'll fill up the array with the appropriate data for you. After this, you should have an array that is $N \times (M * K)$ where $K$ is the number of batches.
Now that we have this array, we can iterate through it to get our batches. The idea is each batch is a $N \times M$ window on the array. For each subsequent batch, the window moves over by n_steps
. We also want to create both the input and target arrays. Remember that the targets are the inputs shifted over one character. You'll usually see the first input character used as the last target character, so something like this:
y[:, :-1], y[:, -1] = x[:, 1:], x[:, 0]
where x
is the input batch and y
is the target batch.
The way I like to do this window is use range
to take steps of size n_steps
from $0$ to arr.shape[1]
, the total number of steps in each sequence. That way, the integers you get from range
always point to the start of a batch, and each window is n_steps
wide.
Exercise: Write the code for creating batches in the function below. The exercises in this notebook will not be easy. I've provided a notebook with solutions alongside this notebook. If you get stuck, checkout the solutions. The most important thing is that you don't copy and paste the code into here, type out the solution code yourself.
def get_batches(arr, n_seqs, n_steps):
'''Create a generator that returns batches of size
n_seqs x n_steps from arr.
Arguments
---------
arr: Array you want to make batches from
n_seqs: Batch size, the number of sequences per batch
n_steps: Number of sequence steps per batch
'''
# Get the number of characters per batch and number of batches we can make
characters_per_batch = n_seqs*n_steps
n_batches = len(arr) // characters_per_batch
# Keep only enough characters to make full batches
arr = arr[:n_batches*characters_per_batch]
# Reshape into n_seqs rows
arr = arr.reshape((n_seqs, -1))
for n in range(0, arr.shape[1], n_steps):
# The features
x = arr[:, n:n+n_steps]
# The targets, shifted by one
y = np.zeros_like(x)
y[:, :-1], y[:, -1] = x[:, 1:], x[:, 0]
yield x, y
Now I'll make my data sets and we can check out what's going on here. Here I'm going to use a batch size of 10 and 50 sequence steps.
batches = get_batches(encoded, 10, 50)
x, y = next(batches)
print('x\n', x[:10, :10])
print('\ny\n', y[:10, :10])
x [[31 64 57 72 76 61 74 1 16 0] [ 1 57 69 1 70 71 76 1 63 71] [78 65 70 13 0 0 3 53 61 75] [70 1 60 77 74 65 70 63 1 64] [ 1 65 76 1 65 75 11 1 75 65] [ 1 37 76 1 79 57 75 0 71 70] [64 61 70 1 59 71 69 61 1 62] [26 1 58 77 76 1 70 71 79 1] [76 1 65 75 70 7 76 13 1 48] [ 1 75 57 65 60 1 76 71 1 64]] y [[64 57 72 76 61 74 1 16 0 0] [57 69 1 70 71 76 1 63 71 65] [65 70 13 0 0 3 53 61 75 11] [ 1 60 77 74 65 70 63 1 64 65] [65 76 1 65 75 11 1 75 65 74] [37 76 1 79 57 75 0 71 70 68] [61 70 1 59 71 69 61 1 62 71] [ 1 58 77 76 1 70 71 79 1 75] [ 1 65 75 70 7 76 13 1 48 64] [75 57 65 60 1 76 71 1 64 61]]
If you implemented get_batches
correctly, the above output should look something like
x
[[55 63 69 22 6 76 45 5 16 35]
[ 5 69 1 5 12 52 6 5 56 52]
[48 29 12 61 35 35 8 64 76 78]
[12 5 24 39 45 29 12 56 5 63]
[ 5 29 6 5 29 78 28 5 78 29]
[ 5 13 6 5 36 69 78 35 52 12]
[63 76 12 5 18 52 1 76 5 58]
[34 5 73 39 6 5 12 52 36 5]
[ 6 5 29 78 12 79 6 61 5 59]
[ 5 78 69 29 24 5 6 52 5 63]]
y
[[63 69 22 6 76 45 5 16 35 35]
[69 1 5 12 52 6 5 56 52 29]
[29 12 61 35 35 8 64 76 78 28]
[ 5 24 39 45 29 12 56 5 63 29]
[29 6 5 29 78 28 5 78 29 45]
[13 6 5 36 69 78 35 52 12 43]
[76 12 5 18 52 1 76 5 58 52]
[ 5 73 39 6 5 12 52 36 5 78]
[ 5 29 78 12 79 6 61 5 59 63]
[78 69 29 24 5 6 52 5 63 76]]
although the exact numbers will be different. Check to make sure the data is shifted over one step for y
.
Below is where you'll build the network. We'll break it up into parts so it's easier to reason about each bit. Then we can connect them up into the whole network.
First off we'll create our input placeholders. As usual we need placeholders for the training data and the targets. We'll also create a placeholder for dropout layers called keep_prob
. This will be a scalar, that is a 0-D tensor. To make a scalar, you create a placeholder without giving it a size.
Exercise: Create the input placeholders in the function below.
def build_inputs(batch_size, num_steps):
''' Define placeholders for inputs, targets, and dropout
Arguments
---------
batch_size: Batch size, number of sequences per batch
num_steps: Number of sequence steps in a batch
'''
# Declare placeholders we'll feed into the graph
inputs = tf.placeholder(tf.int32, (batch_size, num_steps))
targets = tf.placeholder(tf.int32, (batch_size, num_steps))
# Keep probability placeholder for drop out layers
keep_prob = tf.placeholder(tf.float32, ())
return inputs, targets, keep_prob
Here we will create the LSTM cell we'll use in the hidden layer. We'll use this cell as a building block for the RNN. So we aren't actually defining the RNN here, just the type of cell we'll use in the hidden layer.
We first create a basic LSTM cell with
lstm = tf.contrib.rnn.BasicLSTMCell(num_units)
where num_units
is the number of units in the hidden layers in the cell. Then we can add dropout by wrapping it with
tf.contrib.rnn.DropoutWrapper(lstm, output_keep_prob=keep_prob)
You pass in a cell and it will automatically add dropout to the inputs or outputs. Finally, we can stack up the LSTM cells into layers with tf.contrib.rnn.MultiRNNCell
. With this, you pass in a list of cells and it will send the output of one cell into the next cell. Previously with TensorFlow 1.0, you could do this
tf.contrib.rnn.MultiRNNCell([cell]*num_layers)
This might look a little weird if you know Python well because this will create a list of the same cell
object. However, TensorFlow 1.0 will create different weight matrices for all cell
objects. But, starting with TensorFlow 1.1 you actually need to create new cell objects in the list. To get it to work in TensorFlow 1.1, it should look like
def build_cell(num_units, keep_prob):
lstm = tf.contrib.rnn.BasicLSTMCell(num_units)
drop = tf.contrib.rnn.DropoutWrapper(lstm, output_keep_prob=keep_prob)
return drop
tf.contrib.rnn.MultiRNNCell([build_cell(num_units, keep_prob) for _ in range(num_layers)])
Even though this is actually multiple LSTM cells stacked on each other, you can treat the multiple layers as one cell.
We also need to create an initial cell state of all zeros. This can be done like so
initial_state = cell.zero_state(batch_size, tf.float32)
Below, we implement the build_lstm
function to create these LSTM cells and the initial state.
def build_lstm(lstm_size, num_layers, batch_size, keep_prob):
''' Build LSTM cell.
Arguments
---------
keep_prob: Scalar tensor (tf.placeholder) for the dropout keep probability
lstm_size: Size of the hidden layers in the LSTM cells
num_layers: Number of LSTM layers
batch_size: Batch size
'''
### Build the LSTM Cell
def lstm_cell(units, keep_prob):
# Use a basic LSTM cell
lstm = tf.contrib.rnn.BasicLSTMCell(units)
# Add dropout to the cell outputs
drop = tf.contrib.rnn.DropoutWrapper(lstm, output_keep_prob=keep_prob)
return drop
# Stack up multiple LSTM layers, for deep learning
cell = tf.contrib.rnn.MultiRNNCell([lstm_cell(lstm_size, keep_prob) for _ in range(num_layers)])
initial_state = cell.zero_state(batch_size, tf.float32)
return cell, initial_state
Here we'll create the output layer. We need to connect the output of the RNN cells to a full connected layer with a softmax output. The softmax output gives us a probability distribution we can use to predict the next character, so we want this layer to have size $C$, the number of classes/characters we have in our text.
If our input has batch size $N$, number of steps $M$, and the hidden layer has $L$ hidden units, then the output is a 3D tensor with size $N \times M \times L$. The output of each LSTM cell has size $L$, we have $M$ of them, one for each sequence step, and we have $N$ sequences. So the total size is $N \times M \times L$.
We are using the same fully connected layer, the same weights, for each of the outputs. Then, to make things easier, we should reshape the outputs into a 2D tensor with shape $(M * N) \times L$. That is, one row for each sequence and step, where the values of each row are the output from the LSTM cells. We get the LSTM output as a list, lstm_output
. First we need to concatenate this whole list into one array with tf.concat
. Then, reshape it (with tf.reshape
) to size $(M * N) \times L$.
One we have the outputs reshaped, we can do the matrix multiplication with the weights. We need to wrap the weight and bias variables in a variable scope with tf.variable_scope(scope_name)
because there are weights being created in the LSTM cells. TensorFlow will throw an error if the weights created here have the same names as the weights created in the LSTM cells, which they will be default. To avoid this, we wrap the variables in a variable scope so we can give them unique names.
Exercise: Implement the output layer in the function below.
def build_output(lstm_output, in_size, out_size):
''' Build a softmax layer, return the softmax output and logits.
Arguments
---------
lstm_output: List of output tensors from the LSTM layer
in_size: Size of the input tensor, for example, size of the LSTM cells
out_size: Size of this softmax layer
'''
# Reshape output so it's a bunch of rows, one row for each step for each sequence.
# Concatenate lstm_output over axis 1 (the columns)
seq_output = tf.concat(lstm_output, axis=1)
# Reshape seq_output to a 2D tensor with lstm_size columns
x = tf.reshape(seq_output, (-1, in_size))
# Connect the RNN outputs to a softmax layer
with tf.variable_scope('softmax'):
# Create the weight and bias variables here
softmax_w = tf.Variable(tf.truncated_normal((in_size, out_size), stddev=0.1))
softmax_b = tf.Variable(tf.zeros(out_size))
# Since output is a bunch of rows of RNN cell outputs, logits will be a bunch
# of rows of logit outputs, one for each step and sequence
logits = tf.nn.bias_add(tf.matmul(x, softmax_w), softmax_b)
# Use softmax to get the probabilities for predicted characters
out = tf.nn.softmax(logits)
return out, logits
Next up is the training loss. We get the logits and targets and calculate the softmax cross-entropy loss. First we need to one-hot encode the targets, we're getting them as encoded characters. Then, reshape the one-hot targets so it's a 2D tensor with size $(M*N) \times C$ where $C$ is the number of classes/characters we have. Remember that we reshaped the LSTM outputs and ran them through a fully connected layer with $C$ units. So our logits will also have size $(M*N) \times C$.
Then we run the logits and targets through tf.nn.softmax_cross_entropy_with_logits
and find the mean to get the loss.
Exercise: Implement the loss calculation in the function below.
def build_loss(logits, targets, lstm_size, num_classes):
''' Calculate the loss from the logits and the targets.
Arguments
---------
logits: Logits from final fully connected layer
targets: Targets for supervised learning
lstm_size: Number of LSTM hidden units
num_classes: Number of classes in targets
'''
# One-hot encode targets and reshape to match logits, one row per sequence per step
y_one_hot = tf.one_hot(targets, num_classes)
y_reshaped = tf.reshape(y_one_hot, logits.get_shape())
# Softmax cross entropy loss
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_reshaped, logits=logits))
return loss
Here we build the optimizer. Normal RNNs have have issues gradients exploding and disappearing. LSTMs fix the disappearance problem, but the gradients can still grow without bound. To fix this, we can clip the gradients above some threshold. That is, if a gradient is larger than that threshold, we set it to the threshold. This will ensure the gradients never grow overly large. Then we use an AdamOptimizer for the learning step.
def build_optimizer(loss, learning_rate, grad_clip):
''' Build optmizer for training, using gradient clipping.
Arguments:
loss: Network loss
learning_rate: Learning rate for optimizer
'''
# Optimizer for training, using gradient clipping to control exploding gradients
tvars = tf.trainable_variables()
grads, _ = tf.clip_by_global_norm(tf.gradients(loss, tvars), grad_clip)
train_op = tf.train.AdamOptimizer(learning_rate)
optimizer = train_op.apply_gradients(zip(grads, tvars))
return optimizer
Now we can put all the pieces together and build a class for the network. To actually run data through the LSTM cells, we will use tf.nn.dynamic_rnn
. This function will pass the hidden and cell states across LSTM cells appropriately for us. It returns the outputs for each LSTM cell at each step for each sequence in the mini-batch. It also gives us the final LSTM state. We want to save this state as final_state
so we can pass it to the first LSTM cell in the the next mini-batch run. For tf.nn.dynamic_rnn
, we pass in the cell and initial state we get from build_lstm
, as well as our input sequences. Also, we need to one-hot encode the inputs before going into the RNN.
Exercise: Use the functions you've implemented previously and
tf.nn.dynamic_rnn
to build the network.
class CharRNN:
def __init__(self, num_classes, batch_size=64, num_steps=50,
lstm_size=128, num_layers=2, learning_rate=0.001,
grad_clip=5, sampling=False):
# When we're using this network for sampling later, we'll be passing in
# one character at a time, so providing an option for that
if sampling == True:
batch_size, num_steps = 1, 1
else:
batch_size, num_steps = batch_size, num_steps
tf.reset_default_graph()
# Build the input placeholder tensors
self.inputs, self.targets, self.keep_prob = build_inputs(batch_size, num_steps)
# Build the LSTM cell
cell, self.initial_state = build_lstm(lstm_size, num_layers, batch_size, self.keep_prob)
### Run the data through the RNN layers
# First, one-hot encode the input tokens
x_one_hot = tf.one_hot(self.inputs, num_classes)
# Run each sequence step through the RNN with tf.nn.dynamic_rnn
outputs, state = tf.nn.dynamic_rnn(cell, x_one_hot, initial_state=self.initial_state)
self.final_state = state
# Get softmax predictions and logits
self.prediction, self.logits = build_output(outputs, lstm_size, num_classes)
# Loss and optimizer (with gradient clipping)
self.loss = build_loss(self.logits, self.targets, lstm_size, num_classes)
self.optimizer = build_optimizer(self.loss, learning_rate, grad_clip)
Here are the hyperparameters for the network.
batch_size
- Number of sequences running through the network in one pass.num_steps
- Number of characters in the sequence the network is trained on. Larger is better typically, the network will learn more long range dependencies. But it takes longer to train. 100 is typically a good number here.lstm_size
- The number of units in the hidden layers.num_layers
- Number of hidden LSTM layers to uselearning_rate
- Learning rate for trainingkeep_prob
- The dropout keep probability when training. If you're network is overfitting, try decreasing this.Here's some good advice from Andrej Karpathy on training the network. I'm going to copy it in here for your benefit, but also link to where it originally came from.
Tips and Tricks¶
Monitoring Validation Loss vs. Training Loss¶
If you're somewhat new to Machine Learning or Neural Networks it can take a bit of expertise to get good models. The most important quantity to keep track of is the difference between your training loss (printed during training) and the validation loss (printed once in a while when the RNN is run on the validation data (by default every 1000 iterations)). In particular:
- If your training loss is much lower than validation loss then this means the network might be overfitting. Solutions to this are to decrease your network size, or to increase dropout. For example you could try dropout of 0.5 and so on.
- If your training/validation loss are about equal then your model is underfitting. Increase the size of your model (either number of layers or the raw number of neurons per layer)
Approximate number of parameters¶
The two most important parameters that control the model are
lstm_size
andnum_layers
. I would advise that you always usenum_layers
of either 2/3. Thelstm_size
can be adjusted based on how much data you have. The two important quantities to keep track of here are:
- The number of parameters in your model. This is printed when you start training.
- The size of your dataset. 1MB file is approximately 1 million characters.
These two should be about the same order of magnitude. It's a little tricky to tell. Here are some examples:
- I have a 100MB dataset and I'm using the default parameter settings (which currently print 150K parameters). My data size is significantly larger (100 mil >> 0.15 mil), so I expect to heavily underfit. I am thinking I can comfortably afford to make
lstm_size
larger.- I have a 10MB dataset and running a 10 million parameter model. I'm slightly nervous and I'm carefully monitoring my validation loss. If it's larger than my training loss then I may want to try to increase dropout a bit and see if that helps the validation loss.
Best models strategy¶
The winning strategy to obtaining very good models (if you have the compute time) is to always err on making the network larger (as large as you're willing to wait for it to compute) and then try different dropout values (between 0,1). Whatever model has the best validation performance (the loss, written in the checkpoint filename, low is good) is the one you should use in the end.
It is very common in deep learning to run many different models with many different hyperparameter settings, and in the end take whatever checkpoint gave the best validation performance.
By the way, the size of your training and validation splits are also parameters. Make sure you have a decent amount of data in your validation set or otherwise the validation performance will be noisy and not very informative.
batch_size = 100 # Sequences per batch
num_steps = 100 # Number of sequence steps per batch
lstm_size = 512 # Size of hidden layers in LSTMs
num_layers = 3 # Number of LSTM layers
learning_rate = 0.001 # Learning rate
keep_prob = 0.5 # Dropout keep probability
This is typical training code, passing inputs and targets into the network, then running the optimizer. Here we also get back the final LSTM state for the mini-batch. Then, we pass that state back into the network so the next batch can continue the state from the previous batch. And every so often (set by save_every_n
) I save a checkpoint.
Here I'm saving checkpoints with the format
i{iteration number}_l{# hidden layer units}.ckpt
Exercise: Set the hyperparameters above to train the network. Watch the training loss, it should be consistently dropping. Also, I highly advise running this on a GPU.
epochs = 20
# Save every N iterations
save_every_n = 200
model = CharRNN(len(vocab), batch_size=batch_size, num_steps=num_steps,
lstm_size=lstm_size, num_layers=num_layers,
learning_rate=learning_rate)
saver = tf.train.Saver(max_to_keep=100)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
# Use the line below to load a checkpoint and resume training
#saver.restore(sess, 'checkpoints/______.ckpt')
counter = 0
for e in range(epochs):
# Train network
new_state = sess.run(model.initial_state)
loss = 0
for x, y in get_batches(encoded, batch_size, num_steps):
counter += 1
start = time.time()
feed = {model.inputs: x,
model.targets: y,
model.keep_prob: keep_prob,
model.initial_state: new_state}
batch_loss, new_state, _ = sess.run([model.loss,
model.final_state,
model.optimizer],
feed_dict=feed)
end = time.time()
print('Epoch: {}/{}... '.format(e+1, epochs),
'Training Step: {}... '.format(counter),
'Training loss: {:.4f}... '.format(batch_loss),
'{:.4f} sec/batch'.format((end-start)))
if (counter % save_every_n == 0):
saver.save(sess, "checkpoints/i{}_l{}.ckpt".format(counter, lstm_size))
saver.save(sess, "checkpoints/i{}_l{}.ckpt".format(counter, lstm_size))


| Module | FFMpeg::VideoOptions |
| In: |
lib/ffmpeg/video_options.rb
|
Set color of padded bands. The value for padcolor is expressed as a six digit hexadecimal number where the first two digits represent red, the middle two digits green and last two digits blue (default = 000000 (black)).
Set frame size. The format is `wxh’ (ffserver default = 160x128, ffmpeg default = same as source). The following abbreviations are recognized:
'sqcif' 128x96 'qcif' 176x144 'cif' 352x288 '4cif' 704x576 'qqvga' 160x120 'qvga' 320x240 'vga' 640x480 'svga' 800x600 'xga' 1024x768 'uxga' 1600x1200 'qxga' 2048x1536 'sxga' 1280x1024 'qsxga' 2560x2048 'hsxga' 5120x4096 'wvga' 852x480 'wxga' 1366x768 'wsxga' 1600x1024 'wuxga' 1920x1200 'woxga' 2560x1600 'wqsxga' 3200x2048 'wquxga' 3840x2400 'whsxga' 6400x4096 'whuxga' 7680x4800 'cga' 320x200 'ega' 640x350 'hd480' 852x480 'hd720' 1280x720 'hd1080' 1920x1080
Set video bitrate tolerance (in bits, default 4000k). Has a minimum value of: (target_bitrate/target_framerate). In 1-pass mode, bitrate tolerance specifies how far ratecontrol is willing to deviate from the target average bitrate value. This is not related to min/max bitrate. Lowering tolerance too much has an adverse effect on quality.
`-vcodec codec’ Force video codec to codec. Use the copy special value to tell that the raw codec data must be copied as is.
Set min video bitrate (in bit/s). Most useful in setting up a CBR encode: ffmpeg -i myfile.avi -b 4000k -minrate 4000k -maxrate 4000k -bufsize 1835k out.m2v It is of little use elsewise.
Select the pass number (1 or 2). It is used to do two-pass video encoding. The statistics of the video are recorded in the first pass into a log file (see also the option -passlogfile), and in the second pass that log file is used to generate the video at the exact requested bitrate. On pass 1, you may just deactivate audio and set output to null, examples for Windows and Unix:
ffmpeg -i foo.mov -vcodec libxvid -pass 1 -an -f rawvideo -y NUL ffmpeg -i foo.mov -vcodec libxvid -pass 1 -an -f rawvideo -y /dev/null


Told about thirty years ago by John Campbell, piper to his pupil, J. F. Campbell.
THERE was a shepherd once who went out to the hill to look after his sheep. It was misty and cold, and he had much trouble to find them. At last he had them all but one; and after much searching he found that one too in a peat hag half drowned; so he took off his plaid, and bent down and took hold of the sheep's tail, and he pulled! The sheep was heavy with water, and he could not lift her, so he took off his coat and he pulled!! but it was too much for him, so he spit on his hands, and took a good hold of the tail and he PULLED!! and the tail broke! and if it had not been for that this tale would have been a great deal longer.
This may be compared with Grimm's Golden Key. I have not given it in Gaelic, because, so far as I remember, the story was never told twice in the same words; and it can be told quite as well in any language. It is very well known in many districts in various shapes. I have a second version, which is called--
2. Ursgeal a' Ghamhna dhuinn, an aill leibh as a thoiseach e, The tale of the Brown Stirk. Do you wish from the beginning?
3. According to a Skye version, a man put the stirk on a house top to eat a tuft of grass; the beast fell down the chimney, and the rupture of the tail was
FINIS.


_Glitter_ (PG-13) no stars (out of ****)
Now that _Glitter_, her feature starring debut, has finally arrived in theatres, the reason for pop/R&B diva Mariah Carey's much-publicized breakdowns (at last count: two) is abundantly clear: the film itself. While the local press screening for "Glitter" played to only a half-capacity crowd, this downsized audience's peals of laughter were loud enough to fill every corner the auditorium--not exactly the hoped-for reaction to an inspirational tearjerker, which is what _Glitter_ so disastrously, laughably strives to be.
_Glitter_ doesn't waste any time exploiting Carey's most frequently showcased assets--and no, I'm not talking about her Grammy-winning pipes. After a brief intro that shows how single (and singing) mother Lillian Frank (Valarie Pettiford) was forced to give up daughter Billie at an early age, Carey's adult Billie is first seen all decked out in fishnet stockings and black lingerie with leopard print trim, shaking her groove thing as a not-quite-exotic dancer at an NYC club, circa 1983. After she and her friends/roommates/dance partners (Da Brat and Tia Texada) are soon offered a gig as back-up singers to a shockingly untalented dance artist, Billie's soaring voice draws the attention of DJ Julian "Dice" Black (British actor Max Beesley, called on to bark his lines in a bad New Yawk accent and flash as much flesh as Carey), who offers her his services as producer. Not long after Billie and her friends start making the club rounds as a Mary Jane Girls-ish trio of trilling trollops, Billie and Dice are offering each other more than just their musical abilities, and Billie's rapid ascent in showbiz is offset by the increasing turbulence in her relationship with Dice.
Carey has stressed that her _Glitter_ role of Billie Frank is far from autobiographical, but the similarities to her true story are staggering. Billie, who is biracial (a fact that the film makes a point of emphasizing), has a big voice to match her big dreams, but she starts off distinctly small-time as a back-up singer for another pop act. Her talents are discovered by someone established in the music business, and they become romantically involved. The pair's relationship turns stormy when he expresses the svengali-like (or should I say "Mottola-like"?) desire to steer both her career and her life, including controlling her mode of dress. And so on.
But the blatant parallels to Carey's own story are the only aspects to _Glitter_ that bear any resemblance to real life. The film may be a wish fulfillment fantasy aimed at teen and pre-teen girls, but director Vondie Curtis Hall (who previously directed the very entertaining--in the right way--_Gridlock'd_) and screenwriter Kate Lanier's similarly naive depiction of the music business is laughable. Billie gets a record deal literally overnight and without ever signing on a single dotted line. Billie becomes a major star without a single significant concert date nor television appearance, and MTV was two years old at the time the film is set and already an influential force. Come to think of it, there's no reason why this film is set in the 1980s--everyone looks like they could be from the '90s or 2001, for that matter--except to give Carey a chance to cover and/or sample the R&B hits of the era (most prominently, Cherrelle's "I Didn't Mean to Turn You On"), which, in the film's storyline, are original hits by Billie--hence giving Miss Mariah a history-rewriting ego boost.
Then again, the film is designed as one huge ego boost for its star. Instead, however, it comes off as one huge embarrassment, and much of the blame goes to Miss Mariah herself. She spends the whole film in a state of vacant, wide-eyed, smiley catatonia--that is, whenever she's not passing off a constipated look as one of "sadness" or lipsynching to her own prerecorded vocal tracks (and quite horribly at that; one would think that a decade's worth of music video experience would've given her that one ace-in-the-hole). As in all of her recent videos, Carey also shows a lot of skin (though this being a PG-13-rated film, she still leaves some threads on), but her ample cleavage--and the inexplicable streak of silver paint that shows up on various areas of her body--can't distract from her awful attempts at acting, not to mention the already laughable situations in which she finds herself. In fact, one of the most hilarious scenes is one of gratuitous body baring: Billie films her first music video wearing a translucent wrap over a silver string bikini, but the wind machine is too strong, and--whoops!--there goes the wrap!
Yet that is just one of the many unintentional moments of high comedy in the howlerfest that is _Glitter_. Just when you think it could not get more ridiculous, Hall, Lanier, and Miss Mariah go that extra mile. A scene where Billie, all decked out in a sequined gown and spike heels, struggles to walk--make that "wobble"--across a lawn and one where a split-up Billie and Dice engage in seemingly telepathic songwriting (if only I were kidding) are instant entries into the Bad Movie Hall of Fame.  If anyone does shed any tears at _Glitter_, it's undoubtedly from busting a gut laughing.
©2001 Michael Dequina
Michael Dequina<EMAIL_ADDRESS>|<EMAIL_ADDRESS>|<EMAIL_ADDRESS>The Movie Report/Mr. Brown's Movie Site: www.mrbrownmovies.com www.filmthreat.com | www.cinemareview.com | www.digitalwidescreen.com on ICQ: #25289934 | on AOL Instant Messenger: MrBrown23
========== X-RAMR-ID: 29773 X-Language: en X-RT-ReviewID: 254069 X-RT-TitleID: 1108787 X-RT-SourceID: 636 X-RT-AuthorID: 1202 X-RT-RatingText: 0/4
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


{% comment %} This is just a stub, pointing the user to the link section. {% endcomment %} {% load i18n %}


My most recent purchase was a Baja Telecaster, my final decision after months of research and flitting between hollow-bodied and solid-bodied guitars. I would strongly recommend it to anybody, and bonded with it very quickly after I first picked it up in a shop back home in Stoke. I still love it!
While the classic 1952-based specification has many advantages, there was one primary feature I grew not to like, and that was the loud buzz when plugged in, but not playing. I’m not talking the standard single-coil hum that is customary of Fender instruments, it was far more severe. I’m talking some sort of grounding problem, since touching any metallic part of the guitar would kill the buzz – I was earthing it.
Scouring the internet for help (my first port of call in many a situation), I found that installing copper shielding was an almost sure-fire way of killing that buzz, at least on a Telecaster. So I set to it.
The main thing you need is adhesive copper tape. It may sound like a tricky and expensive thing to get hold of but it really isn’t. A trick is to visit garden centres or home stores. They sell it to line plant pots, to deter slugs from crawling up and having a chomp on the plants (they get a small electric shock from the copper). Alternatively, I got some on eBay for under £4, which was perfect! (bit.ly/TsZyqS) Try to make sure that the adhesive of the tape is conductive.
Aside from that you need a screwdriver to disassemble/reassemble your guitar, a generous length of wire, and a multimeter if possible.
The first step is to remove the strings and loosen all the components (but don’t detach them, that isn’t necessary). The bridge plate will need to come off though.
Then, when you can get inside the body with little obstruction from the components, get the tape, and line the cavities with it. This may seem like I’m jumping steps here, but it’s really quite a simple and repetitive process. I got my flatmate to help me, to get the job done more quickly! You peel off the back of the tape, and lay it down inside the neck, bridge and control cavities, making sure there’s a little overhang spilling onto the top of the guitar – it’ll make the connection job more thorough! The good thing about foil is that it can mould smoothly into any shape - you’ll have a complete coat in no time. And the whole procedure is completely reversible. <table width="400" border="0" cellspacing="0" cellpadding="2">
</table> Many guides differ in how thorough you need to be. From my experience it’s important to make sure these criteria are fulfilled:
- Full coverage of each cavity, i.e. no gaps.
- A little overhang on the body (but not enough to be visible after the bits are put back on).
- Overlapping strips is key. It’s an easy way to get full and guaranteed coverage (but don’t go mad).
- Most importantly, electrical continuity. This is what the multimeter is for. Insulate a cavity, then make sure you can detect a reading all round it. The aim of the game is to basically make the guitar into a massive capacitor, so you need to ensure the whole thing can conduct. The other guides however claim that you need to solder the strips together, and/or remove the components (pickups etc…) entirely. The first is only required if the adhesive of the tape is not conductive (the tape I linked above is), and the second is only required if you don’t like fiddly work, are planning to replace your pickups anyway, or have too much time on your hands. My procedure took literally half an hour, with no soldering.
Once you have your cavities fully insulated with copper foil, you need to connect them. Take two short lengths of insulated wire (just enough to go between the neck and control cavities, and the bridge and control cavities respectively), strip the ends and use them to connect the neck and bridge cavities with the control plate cavity, via the guitar’s internal tunnels.
You don’t need to solder the wires down, you can instead use copper tape to fix them to the copper-lined floor of the cavity on each end – which is sufficient. Then, make sure that you have enough of an overhang on your control panel to create a copper link between the cavity and the panel itself. This completes the circuit, as the current then goes via the metal components though the output jack and into your grounded amp.
When all is connected, it’s time to reassemble your guitar. Note the more noticeable overhang on the neck cavity, this is because the pickguard will cover it, and so there is less need to be stingy with the copper:
As well as lining the body cavities with copper, it’s also a good idea to coat the underside of your pickguard with tape. It’s super easy.
That’s it! I plugged it in, went on a ‘metal’ setting on my amp (high gain etc…) and it no longer screamed and hummed. On a ‘clean’ sound, the guitar was silent when not playing – the shielding really does work wonders. And all in under an hour and for less than four pounds.
If you have a single-coil guitar with a similar problem I wish you luck!


X-Rays are walk-in and free for EHHOP patients.
Senior Clinician
Please ask your patient to go to the 6th floor of 17 East 102nd Street any time between 9 am and 4:30pm M-F. During sign-out, let the head TS know that your patient needs an X-Ray and why the referral is necessary. No additional paperwork is required.
Teaching Senior
Please place an order for the referral on Epic. Please include the referral in the email to<EMAIL_ADDRESS>after clinic.
Access to Care Team
No need to see patient unless the clinic team requests it. If the clinic team requests you see the patient, please ask them to go to the 6th floor of 17 East 102nd Street any time between 9am and 5pm M-F.
Cost
Cost to EHHOP Patient: Free
Cost to society:
Chest X-ray ~$370 Knee X-Ray ~$200 Skull X-Ray ~$290 Abdominal X-Ray ~$240 X-Ray Spine ~$280 Shoulder X-Ray ~$210 X-Ray Rib ~$220 Hip X-Ray ~$260 Foot X-Ray ~$280
Wait time
Appointments are walk-in. Patients can receive their X-Rays whenever they go to 6th floor CAM during the weekday.


?
Back
Save
2D setup
Strip or panel:
1D Strip
2D Matrix
Matrix Generator
>
Panel dimensions (WxH):
x
Horizontal panels:
Vertical panels:
1
st
panel:
Top
Bottom
Left
Right
Orientation:
Horizontal
Vertical
Serpentine:
Pressing Populate will create LED panel layout with pre-arranged matrix.
Values above
will not
affect final layout.
WARNING: You may need to update each panel parameters after they are generated.
Populate
Panel set-up
Number of panels:
A matrix is made of 1 or more physical LED panels.
Each panel can be of different size and/or have different LED orientation and/or starting point and/or layout.
LED panel layout
Gap file:
Upload
Note: Gap file is a
.json
file containing an array with number of elements equal to the matrix size.
A value of -1 means that pixel at that position is missing, a value of 0 means never paint that pixel, and 1 means regular pixel.
Back
Save


|
|
|
Name | {{elem.metadata?.name}} | SSH Address | {{elem.ssh_addr}} | SSH Port | {{elem.ssh_port}} | SSH User | {{elem.ssh_cred?.user}} | Administrator | {{elem.op_cred?.user}} | Comment | {{elem.comment}} | Created At | {{elem.metadata?.created_at? (elem.metadata.created_at | date: 'medium'): ''}} | Updated At | {{elem.metadata?.updated_at? (elem.metadata.updated_at | date: 'medium'): ''}} |
|
|---|


Recently I had to write some scripts in PowerShell. Because I try to follow good software development practices I decided to split script logic into functions. First I defined a few functions that taken or returned single value:
Of course they worked brilliantly:
But then I needed to declare function that takes three arguments, I started with code:
Unfortunatelly it didn’t work as expected:
After a bit of research it turned out that PowerShell uses space as argument separator. So to pass three arguments we need to write:
This also works with single argument functions:
Before we end let’s find out what exactly is (1, 2, 3)
and why calling printArg(1)
works.
It turns out that
(a, b, ..., z)
expression represents array of objects in PowerShell:
And (x)
expression represents just x
value :
and thats explain outputs of printArg(1)
and manyArgs(1, 2, 3)
command.
This behaviour of PowerShell may be surprising for C# programmers, I hope this post will help you remember about this problem.


| 013:006 Khan | : |
They ask you to hasten the evil before the good, yet (many) exemplary punishments have indeed occurred before them.  And verily, your Lord is (also) Severe in punishment. |
| 013:006 Maulana | : |
And they ask thee to hasten on the evil before the good and indeed there have been exemplary punishments before them.  And surely thy Lord is Severe in requiting. |
| 013:006 Pickthal | : |
And they bid thee hasten on the evil rather than the good, when exemplary punishments have indeed occurred before them. But lo! thy Lord is rich in pardon for mankind despite their wrong, and lo! thy Lord is strong in punishment. |
| 013:006 Rashad | : |
They challenge you to bring doom upon them, rather than turning righteous! Sufficient precedents have been set for them in the past. Indeed, your Lord is full of forgiveness towards the people, in spite of their transgressions, and your Lord is also strict in enforcing retribution. |
| 013:006 Sarwar | : |
They ask you to bring upon them punishment before they ask you for mercy. Such punishments were already brought upon the people who lived before them. Your Lord, certainly, has forgiveness for the injustice of the people. He is also stern in His retribution. |
| 013:006 Shakir | : |
And they ask you to hasten on the evil before the good, and indeed there have been exemplary punishments before them; and most surely your Lord is the Lord of forgiveness to people, notwithstanding their injustice; and most surely your Lord is severe in requiting (evil). |
| 013:006 Sherali | : |
And they ask thee to hasten on the evil rather than the good, whereas exemplary punishment have already come to pass before them. And, verily, thy Lord is full of forgiveness for mankind despite their wrongdoing, and verily, thy Lord is also Severe in retribution. |
| 013:006 Yusufali | : |
They ask thee to hasten on the evil in preference to the good: Yet have come to pass, before them, (many) exemplary punishments! But verily thy Lord is full of forgiveness for mankind for their wrong-doing, and verily thy Lord is (also) strict in punishment. |
Concepts/Themes Covered: أركان الإسلام > التوحيد > توحيد الله تعالي > ربوبيته جلّ وعلا Pillars of Islam> Islamic> Oneness of Allah> His Divinity, the Great and Almighty أركان الإسلام > التوحيد > توحيد الله تعالي > صفات الله تعالى > ذو مغفرة Pillars of Islam> Islamic> Oneness of Allah> His Glory's Characteristics> Full of Forgiveness أركان الإسلام > التوحيد > توحيد الله تعالي > صفات الله تعالى > شديد العقاب Pillars of Islam> Islamic> Oneness of Allah> His Glory's Characteristics> Strongly Enforces the Punishment أركان الإسلام > التوحيد > الكافرون > تعنت الكفار واستعجالهم بالعذاب Pillars of Islam> Islamic> The Disbelievers> The Disbelievers' Stubbornness and their Acceleration to Torture أركان الإسلام > التوحيد > الملحدون المنكرون ليوم البعث Pillars of Islam> Islamic> The Apostates Who Denies the Resurrection
This tool uses eight English parallel translations for the Holy Quran imported from Mr. Clay Smith. You can also visit Qurany Concepts for browsing the Quran themes or topics. If you want to search the Holy Quran for keywords, please visit Qurany Keywords.


| Electricity | 12 m^3/s |
| Water | 12 m^3/s |
| Gas | 12 m^3/s |
| Device | Usage |
|---|---|
| Fridge | 4 kW/s |
| Kettle | 3 kW/s |
| Kettle | 3 kW/s |
| Kettle | 3 kW/s |
| Kettle | 3 kW/s |
| Kettle | 3 kW/s |
| Kettle | 3 kW/s |
| Kettle | 3 kW/s |
| Kettle | 3 kW/s |
| Kettle | 3 kW/s |
| Kettle | 3 kW/s |
| Kettle | 3 kW/s |
| Kettle | 3 kW/s |
| Kettle | 3 kW/s |


https://github.com/amaclean199/switch-jockey
Choose a provided set:
Set 1
Set 2
Set 3
Or upload a folder:
START
Brightness
Change
Toggle Sliders
Level
Valence
Valence:
0.0
Arousal
Arousal:
0.0
Complexity
Contrast
Movement


Character Generator
Nation:
Random
Feretti Kingdom
Ekkionlor
Junjian Empire
Republic of Toras
Republic of Besizottia
Rotali Sultanate
Republic of Pentiga
Republic of Santeno
Kingdom of Abrax
Race:
Random
Human
Youdel
Lafahl
Age:
Random
Toddler
Child
Adult
Elder
Gender:
Random
Male
Female
Stats
Generate another...


Problem 2 - DAO Pattern, Leaky Abstraction
There is a problem with the DAO Pattern that AutoFetch solves so let's look at an example.
customerDao.findById(Integer id); A DAO Developer builds a customer find by id method and there are
2 developers that want to use this method.
Developer 1 really just needs the customers name and status.
Developer 2 wants all the properties on the customer and the customer's shipping and billing address.
In running the application it is decided there is a performance problem. The query executed is not
suited for use in either of the two cases. The DAO Developer wants to tune the query to perform better
and so he decides to provide 2 methods tuned for use by each of the developers.
public Customer findByIdWithName(Integer id){
Query<Customer> query = Ebean.createQuery(Customer.class);
query.setId(id);
query.select("id,name");
return query.findUnique();
}
public Customer findByIdWithAddresses(Integer id){
Query<Customer> query = Ebean.createQuery(Customer.class);
query.setId(id);
query.join("shippingAddress");
query.join("billingAddress");
return query.findUnique();
}
Now what happens if there are other use cases that use other completely different parts of a Customer?
Should we continue adding a method for each situation? Leaky abstraction perhaps? Is the implementation
detail of the customerDao leaking back up into the application code?
This issue becomes more of a problem as the application gets larger and performance more critical.
Problem 2 - solution
With AutoFetch a single query can be tuned different according to the call stack that was used to call
the query. For example it can tune the query for both use cases differently giving optimal query performance
for both developer 1 and developer 2.
NEXT: Using AutoFetch with Ebean
|


With experience in Ruby on Rails, JavaScript and React and a background in Retail and Customer Service, I discovered web development through an online interactive platform that teaches coding. I bring strong skills in time management, organization and adaptability that help maximize efficiency and operations.
My SkillsActiveRecord | Sinatra | REST API
Bootstrap | Responsive Design
JQuery | JSON | React
OAuth | SQLite | RSpec | Git


You Know, like finding clients, managing them, organizing, collecting money....
PhotoMasters will do it all so you can focus on what you do best: Photography.
Just drop in your email below and we'll do the rest


Match Play 4-4 to 7. How should Red play 21?
pips Red=107 White=111
(CorrectAnswer= 0/0, ErrorScore= 0)
A banana split is definitely required or else White will have an easy run home. The question is how big a play to make?
Over the board I chose 6/5, 6/4* but that play is not big enough. Any entering number by White is likely to be good enough.
Red has to play for a closeout and the best way to do that is 13/11, 5/4*. If White fans once Red will reasonable chance of winning the game and perhaps even a gammon. Even with that play Red only wins a third of the time and a high percentage of his losses will be gammon whatever he does so he may as well go for broke.
Any play other than 13/11, 5/4* an error and my play was very nearly a blunder.
Over the board I chose 6/5, 6/4* but that play is not big enough. Any entering number by White is likely to be good enough.
Red has to play for a closeout and the best way to do that is 13/11, 5/4*. If White fans once Red will reasonable chance of winning the game and perhaps even a gammon. Even with that play Red only wins a third of the time and a high percentage of his losses will be gammon whatever he does so he may as well go for broke.
Any play other than 13/11, 5/4* an error and my play was very nearly a blunder.
1. Cubeful 2-ply 13/11 5/4* Eq.: -0.456 0.347 0.114 0.001 - 0.653 0.373 0.056 2. Cubeful 2-ply 18/16 5/4* Eq.: -0.498 (-0.042) 0.346 0.116 0.001 - 0.654 0.415 0.118 3. Cubeful 2-ply 8/6 5/4* Eq.: -0.503 (-0.047) 0.341 0.118 0.001 - 0.659 0.407 0.094 4. Cubeful 2-ply 11/9 5/4* Eq.: -0.507 (-0.051) 0.345 0.117 0.001 - 0.655 0.423 0.133 5. Cubeful 2-ply 6/5 6/4* Eq.: -0.519 (-0.063) 0.326 0.095 0.001 - 0.674 0.377 0.082


Graphical methods are commonly used for exploratory data analysis. Boxplots, scatterplot matrices, nonparametric smoothers and tree diagrams are just some of the most used graphical tools for data exploration. This part of the course will provide practical recommendations for choosing the best chart or graph type for creating good and clear graphics that will serve the purpose of communicating the key information
Good and clear graphics rely most of all on reliable data. Thus, the first principle of an effective visualisation is that it represents reliable information. The type of information that needs to be communicated and displayed will direct the choice of the most appropriate type of data encoding to make relevant patterns become noticeable. It is therefore important to understand the problem you wish to communicate and the type of the data you need for its communication from the statistical perspective, ie. is it measured, categorical (ordinal or nominal), time (temporal dimension) or geographical location (spatial dimensions) in case of spatiotemporal data?
Visual encoding of a data set depends on the number and characteristics of the available attributes ie. variables and on the analytical problem in question. Alberto Cairo in his blog The Functional Art provides an effective list of the graphic forms used to encode data depending on the function of the display. The figure shows ranking of the elementary perception task according to how well they can be perceived based on the ground breaking work of Cleveland and McGill published in the paper of JASA while working in the famous AT&T Bell Labs.
The above figure illustrates the order in which graphical forms could be placed based on the accuracy of the conclusions which readers can draw about the given data from them. If, for example, the goal of the graphic is to facilitate precise comparisons, Alberto in his book The Functional Art provides an effective illustration of superiorities between possible choices of the graphical forms that could be used.
There is not a specific methodology that is develop for choosing the most appropriate ways of encoding data. You never know if a visual form will work until you give it a try. It mostly depends on what your the attributes are that you using in order to reveal that special something from the data. However, there are some useful guidelines made by a few authors which I would recommend you to check:
as a starting bench mark when creating a graph.
Often, the graphical display of the information created for answering a specific question will invite further exploration, which is why it is important to present them in a clear and truthful manner. We should not forget that the sole purpose of data analysis, thus visualisation, is to inform and to improve knowledge. So yes, we should consider very carefully the aesthetic appeal and design of the graph we create that could effectively engage with the audience, but should do so by focusing above all on the accuracy, depth and clarity of the information it is conveying.
Let us play the game ‘Identify encoding!’. Converse with each other and make a list of graphical forms and the type of encodings used in each of the following visualisation:
Click on this Visualisation too: A Periodic Table of visualisation methods
The most important thing to remember when creating a graph is to present data clearly and truthfully. The choice of the scale on the chart should show the differences in the data and communicate the range of values accurately. Any statistical summary displayed on the chart should be presented clearly with the source of information and statistics used to calculate the more complex figures.
Here are some most obvious issues you need to pay attention to when designing an effective graph:
The choice of scale should allow for better accuracy that the reader can draw about the information displayed on the chart.
Have a look at What to consider when creating a line chart blog post by Lisa Charlotte Rost, where you will also find links to some more interesting posts on this topic.
Sometimes it might be effective to pull the key information from a chart into separate graphs and to present them in paralell.
Keep in mind that the information from the visual display should not be confusing.
Integrate text with the graphs only if necessary to help better convey information displayed through the graph.
In this presentation Alberto Cairo illustrates the importance of a good choice of the format used to visually explain the main story: “How Music Preferences Have Changed in Two Decades”.
When creating a data visualisation, think about the specific information that you want your data to convey, or the outcome that you want to achieve. Keep it simple and remove any unnecessary elements that could convolute your central point. Bombarding an audience with too much data will likely leave them doubtful and confused.
When creating a graphical display, focus on best practices and explore your own personal style. Build a foundation of exploring and summarising a set of numbers and identifying the key feature within the data that will help you in presenting your visual data story.
There is a belief that charts with two different y-axes make it hard for most people to read and to make the right conclusions about two data sets. Having a secondary y-axis often creates confusion as it is not clear which data to read against which axis. The main danger of dual axis charts is that they’re not intuitive. There are many people who are opposing them as they often create confusion and assume correlation when there is none. Stephen Few however, has written a well-argued paper in which he carefully presents issues one needs to take into consideration when wanting to use them. You need to judge for yourself if you are going to be a fan or not of dual y-axis charts. It should certainly depend on your judgment of its suitability for conveying your graphical story telling as with any other graphical format.
Interactivity allows the viewer to engage with data in ways impossible by static graphs. One of the key benefits of interactive data visualisations is their flexibility in allowing further manipulation and exploration of the data used. By enabling concentrated focus using the ‘zoom in’ facility, it makes discovery of the seemingly small facts in a big story easy and engaging, as users are invited to pose additional questions and come up with new findings. Interactive graphical story telling is a rich and powerful tool for displaying data features as it enables viewers to dive into the data story as much or as little as they wish, depending on their level of interest.
R is a great tool for data visualisation not just for people who want to develop understanding about their data using graphs, but anyone who needs to produce high-quality and effective graphics to enhance their reports, web pages, or other documents.
Take a look at The R Graph Gallery that provides an extensive collection of charts made in R together with the code.
There are several clasic books on drawing graphics in R, such as:
If you would like to get more serious and systematic in your learning about graphical data analysis with R, a book by Antony Unwin, Graphical Data Analysis with R, is a great place to start. The R code for every graphic and analysis in the book is available from the book's website.
Data Visualisation with R by Rob Kabacoff is another good book about graphical displays in R. It gives a systematic overview for creating graphical displays in R starting with a brief introduction to R, followed by a comprehensive list of graphical forms commonly used in statistical modelling, geospatial mapping and finishing with interactive plots.
Back in 2012 there was a very engaging academic discussion between Andrew Gelman, Anthony Unwin, Stephen Few, Paul Murrell, Hadley Wickham and Robert Kosara about visualisation and infographics. Robert compiles all the discussion posts in this blog post that makes riveting reading.
Practise! Gaining experience in interpreting graphics and drawing your own data displays is the most effective way of becoming a data wiz.
© 2020 Tatjana Kecojevic


{% block head %}
{% block title %}Cook With Me{% endblock %}
{% endblock %} {% if current_user.is_authenticated %} Hi {{ current_user.name }}! {% endif %}
Home
(current)
Blog
(current)
Recepies
(current)
About
(current)
Contact
(current)
FAQS
(current)
{% block content %} {% endblock %}


Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
1 Websites There are many varitions of passages of Lorem Ipsum
228MB Hosting Space There are many varitions of passages of Lorem Ipsum
1 Free Domain Hosting There are many varitions of passages of Lorem Ipsum
No Support There are many varitions of passages of Lorem Ipsum
1GB Monthly Bandwidth There are many varitions of passages of Lorem Ipsum
Contact10 Websites There are many varitions of passages of Lorem Ipsum
1GB Hosting Space There are many varitions of passages of Lorem Ipsum
5 Free Domain Hosting There are many varitions of passages of Lorem Ipsum
12/3 Support There are many varitions of passages of Lorem Ipsum
25GB Monthly Bandwidth There are many varitions of passages of Lorem Ipsum
Contact60 Websites There are many varitions of passages of Lorem Ipsum
10GB Hosting Space There are many varitions of passages of Lorem Ipsum
100 Free Domain Hosting There are many varitions of passages of Lorem Ipsum
24/7 Support There are many varitions of passages of Lorem Ipsum
250GB Monthly Bandwidth There are many varitions of passages of Lorem Ipsum
ContactLorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
 Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
Unlimited Bandwidth
Attendee’s Welcome Gift
100GB Extrernal Memory
10 Free Domain Hosting
24/7 Support
Order NowLorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.


description = "results-section" [viewBag] ==
| {{" "|raw}}Suppliers of {{ search }}: |
|---|
|
{{ company.name }}
{{ company.vendor_data }}
|
Sorry, no results found. Please try your search again.
{% endif %} {% endif %}


Now why does this film seem familiar?
The Rage: Carrie 2 A Film Review By Michael Redman Copyright 1999 By Michael Redman
*1/2 (Out of ****)
"There's nothing new under the sun" is a phrase often used when the speaker actually means "Let's find something to copy."
Of course there are very few completely original ideas. Even earth-shattering concepts are built upon the vast body of human experience. There is, after all, no need to re-invent the wheel time after time.
Recently it seems that Hollywood doesn't feel the need to even re-write the script.
My understanding of the word "sequel" is a continuation of the story. The film industry has defined the word to mean reshooting the original with minor changes.
Have an overwhelming desire to see an inferior version of Brian DePalma's adaptation of the Steven King novel? This is your dream come true.
Rachel (Emily Bergl), a high school outcast, is beginning to notice weird things happening around her. Doors slam shut by themselves.
 A popular boy unexpectedly asks her out. The in-crowd conspires to embarrass her at a public event.
Any of this sound familiar?
Once the audience catches on that this is the same story as "Carrie", there's little to do but wait for the inevitable ending. The effects are a bit better this time around, but the film doesn't work nearly as well.
There are a couple of minor plot differences. Rachel lives with foster parents because her mother is institutionalized. The boys at her school are portrayed as even more evil than in the original. They keep score of their scoring with points given for each conquest. And, uh, there must be other story changes but none stand out.
One nice touch is the casting of Amy Irving again as Sue Snell. Over 20 years ago she was the one girl who tried to help Carrie. Now a high school counselor, she befriends Rachel, but her character's potential is squandered.
There's too much about Sue that doesn't make sense. After the slaughter when Carrie kills most of her classmates, Sue is driven mad and spends time in the institution that Rachel's mother is in. Still living in the same small town, the woman with a well-known history of mental problems is hired as a high school counselor?
Sue tells Rachel that her telekinesis is a genetic disease. This may be the one original idea in the film, but the reasoning behind describing psychic powers as a "disease" is never explained.
Sue's eventual fate is an admission by director Katt Shea and writer Rafael Moreu that they had an interesting character but couldn't figure out what to do with her. Blink and you'll miss it.
Some of the events are filmed in black and white, but the rationale for this is unknown. It doesn't add anything and the choice of scenes appears somewhat random.
"The Rage" retains some of the trappings of "Carrie" without the meaning. In the first film the color red was a motif connected to Carrie's onset of powers at the same time she began menstruating. Here there's an abundance of red, but for no apparent purpose.
The casting of high school jocks and cheerleaders as villains is beginning to wear thin. One might be lead to suspect that most filmmakers were unpopular in school and the history of teenage films is an extended cinematic revenge of the nerds.
The biggest mistake the film makes is including clips of the original. Seeing Sissy Spacek on the screen only points to the quality of that film - and the flaws in this one.
(Michael Redman has written this column since "Carrie" was released and thought about just re-writing his review of it for "The Rage". Email copies of old letters to<EMAIL_ADDRESS>[This appeared in the 3/18/99 "Bloomington Independent", Bloomington, Indiana. Michael Redman can be contacted at<EMAIL_ADDRESS>--<EMAIL_ADDRESS>This week's film review: http://www.indepen.com/ Film reviews archive: http://us.imdb.com/M/reviews_by?Michael%20Redman Y2K articles: http://www.indepen.com/
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


Construct Binary Search Tree From Preorder Traversal
Return the root node of a binary search tree that matches the given preorder traversal. (Recall that a binary search tree is a binary tree where for every node, any descendant of node.left has a value < node.val, and any descendant of node.right has a value > node.val. Also recall that a preorder traversal displays the value of the node first, then traverses node.left, then traverses node.right.) Example 1 Input: [8,5,1,7,10,12] Output: [8,5,10,1,7,null,12] Note: 1 <= preorder.


OverviewThis tutorial is designed to provide a basic overview of how to use HttpClient. When you have completed the tutorial you will have written a simple application that downloads a page using HttpClient. It is assumed that you have an understanding of how to program in Java and are familiar with the development environment you are using. Getting ReadyThe first thing you need to do is get a copy of HttpClient and its dependencies. This tutorial was written for HttpClient 3.0. You will also need JDK 1.3 or above. Once you've downloaded HttpClient and dependencies you will need to put them on your classpath. There is also an optional dependency on JSSE which is required for HTTPS connections; this is not required for this tutorial. ConceptsThe general process for using HttpClient consists of a number of steps:
We'll cover how to perform each of these steps below. Notice that we go through the entire process regardless of whether the server returned an error or not. This is important because HTTP 1.1 allows multiple requests to use the same connection by simply sending the requests one after the other. Obviously, if we don't read the entire response to the first request, the left over data will get in the way of the second response. HttpClient tries to handle this but to avoid problems it is important to always release the connection. It is important to always release the connection regardless of whether the server returned an error or not. Instantiating HttpClientThe no argument constructor for HttpClient client = new HttpClient(); Creating a MethodThe various methods defined by the HTTP specification correspond to
the various classes in HttpClient which implement the HttpMethod
interface. These classes are all found in the package
We will be using the Get method which is a simple method that simply takes a URL and gets the document the URL points to. HttpMethod method = new GetMethod("http://www.apache.org/"); Execute the MethodThe actual execution of the method is performed by calling
There are two kinds of exceptions that could be thrown by
executeMethod, The other useful piece of information is the status code that is returned by the server. This code is returned by executeMethod as an int and can be used to determine if the request was successful or not and can sometimes indicate that further action is required by the client such as providing authentication credentials. HttpExceptionAn HttpException represents a logical error and is thrown when the request cannot be sent or the response cannot be processed due to a fatal violation of the HTTP specification. Usually this kind of exceptions cannot be recovered from. For a detailed discussion on protocol exceptions please refer to the HttpClient exception handling guide. Note that HttpException actually extends IOException so you can just ignore it and catch the IOException if your application does not distinguish between protocol and transport errors. IOExceptionA plain IOException (which is not a subclass of HttpException) represents a transport error and is thrown when an error occurs that is likely to be a once-off I/O problem. Usually the request has a good chance of succeeding on a second attempt, so per default HttpClient will try to recover the request automatically. For a detailed discussion on transport exceptions please refer to the HttpClient exception handling guide. Method recoveryPer default HttpClient will automatically attempt to recover from the not-fatal errors, that is, when a plain IOException is thrown. HttpClient will retry the method three times provided that the request has never been fully transmitted to the target server. For a detailed discussion on HTTP method recovery please refer to the HttpClient exception handling guide // set per default client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler()); Default recovery procedure can be replaced with a custom one. The number of automatic retries can be increased. HttpClient can also be instructed to retry the method even though the request may have already been processed by the server and the I/O exception has occurred while receiving the response. Please exercise caution when enabling auto-retrial. Use it only if the method is known to be idempotent, that is, it is known to be safe to retry multiple times without causing data corruption or data inconsistency. The rule of thumb is GET methods are usually safe unless known otherwise, entity enclosing methods such as POST and PUT are usually unsafe unless known otherwise. DefaultMethodRetryHandler retryhandler = new DefaultMethodRetryHandler(10, true); client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, retryhandler); Read the ResponseIt is vital that the response body is always read regardless of the status returned by the server. There are three ways to do this:
For this tutorial we will use byte[] responseBody = method.getResponseBody(); Release the ConnectionThis is a crucial step to keep things flowing. We must tell HttpClient that we are done with the connection and that it can now be reused. Without doing this HttpClient will wait indefinitely for a connection to free up so that it can be reused. method.releaseConnection(); Deal with the RepsonseWe've now completed our interaction with HttpClient and can just concentrate on doing what we need to do with the data. In our case, we'll just print it out to the console. It's worth noting that if you were retrieving the response as a stream and processing it as it is read, this step would actually be combined with reading the connection, and when you'd finished processing all the data, you'd then close the input stream and release the connection. Note: We should pay attention to character encodings here instead of just using the system default. System.err.println(new String(responseBody)); Final Source CodeWhen we put all of that together plus a little bit of glue code we get the program below. import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.methods.*; import org.apache.commons.httpclient.params.HttpMethodParams; import java.io.*; public class HttpClientTutorial { private static String url = "http://www.apache.org/"; public static void main(String[] args) { // Create an instance of HttpClient. HttpClient client = new HttpClient(); // Create a method instance. GetMethod method = new GetMethod(url); // Provide custom retry handler is necessary method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(3, false)); try { // Execute the method. int statusCode = client.executeMethod(method); if (statusCode != HttpStatus.SC_OK) { System.err.println("Method failed: " + method.getStatusLine()); } // Read the response body. byte[] responseBody = method.getResponseBody(); // Deal with the response. // Use caution: ensure correct character encoding and is not binary data System.out.println(new String(responseBody)); } catch (HttpException e) { System.err.println("Fatal protocol violation: " + e.getMessage()); e.printStackTrace(); } catch (IOException e) { System.err.println("Fatal transport error: " + e.getMessage()); e.printStackTrace(); } finally { // Release the connection. method.releaseConnection(); } } } |


Today: 28 May 2019
Settings
Companies
| ID | Company | Period | Removed |
|---|---|---|---|
| 1 | The Pixel Age (TPA) | May 2018 - May 2019 | |
| 2 | The Shipyard Private Limited (TSY) | Nov 2015 - May 2018 |
Projects
| ID | Project | Code | Removed |
|---|---|---|---|
| 1 | Personal Project | PROJ | |
| 2 | Prototype / Proof-of-Concept | POC |
Years
| ID | Year | Removed |
|---|---|---|
| 1 | 2019 | |
| 2 | 2018 | |
| 3 | 2017 |
Day-types
| ID | Name | Icon (FA) | Color (Hex) | Removed |
|---|---|---|---|---|
| 1 | Misc | #9e9e9e | ||
| 2 | Others | #9e9e9e | ||
| 3 | Work Day (regular) | #607d8b | ||
| 4 | Public Holiday | #009688 | ||
| 5 | Annual Leave | #ff9800 | ||
| 6 | Medical Leave | #e91e63 | ||
| 6 | Compassionate Leave | #8e24aa | ||
| 6 | Company Events | #3f51b5 |


On a grid map, line drawing is useful for for visibility, the path of an arrow/bullet, and enemy AI. There are several fast algorithms for this but I prefer using a very simple algorithm. Here's the algorithm in action:
Let's look at linear interpolation, or lerp, for numbers:
lerp( 0, 1, ) = lerp( 0, 100, ) = lerp( 3, 5, ) = lerp( 5, 3, ) =
Let's look at linear interpolation for points. We can separately linearly interpolate the x and y values, and it behaves as we might expect:
Try varying t = .
Instead of picking 1 interpolation point, let's pick N of them:
Try varying N = .
Now let's round each of those N points to the closest grid square:
Try varying N = until it reaches the optimal value of = max(Δx,Δy).


This section covers functionality referring to administrative details
2.7.1 Accessing Gradebooks 2.7.2 Predicting Grades 2.7.3 Electronic Turn In


Use these details in your returns
The data return you’re going to send is about:
| File name | EA_ID | Site_Name |
|---|---|---|
| AB23456 | Sandy Shore Farm Quarry and Landfill |
The data return you’re going to send is about:
| File name | EA_ID | Site_Name |
|---|---|---|
| AB23456 | Sandy Shore Farm Quarry and Landfill |


{{storage.slusFiltered.length}} OSDs
Note: Be aware that the PG count per pool value is critical for cluster performance and stability. Please visit the Ceph PGs per Pool Calc tool to better understand what value should be used.


{{flash}}
Please sign in
Sign in
User information
Email
First Name
Last Name
Password
Password must be at least 8 characters
Password do not match
Security
User auth token
{{token}}
Security contexts ({{context}})
user:{{user.email}}
Active
resource:{{k}}
Active
CORS origins
{{origin}}
Submit changes
Logout


I have 3 years of experience of developing enterprise software.I have profound interest in Computer Science fundamentals.I have completed Bachelors of Engineering from Pune University,India. I am pursuing Master's Degree in Computer Science at The University of Texas, Arlington with current GPA: 4 I enjoy developing things that live on the internet, whether that be websites, applications, or anything in between.
Project 2: Aadhaar Verify Android App & AadhaarAPI website
Project 3: Voter Id Bill and Credit Score Verification
Project 4: Offline KYC
Arlington, Texas, USA(Jan 2020 - Present)
Master of Science •Computer Science
GPA: 4.0
Pune Maharashtra,India(Aug 2012 - May 2016)
Bachelor of Engineering
Grade: First Class
Implementation of various concepts in AI in python2
Python
The aim of this project is to design and develop an android app for 3 kinds of user: guest, admin & manager and perform their functionalities.
Actively involved in every aspect of application development.
Android Studio
SQL
Java
Design Pattern
UML Diagram
Use Case Diagram
Expanded Use Cases
Domain Model
UI ProtoTypes
Design Class Diagram
Sequence Diagram
A simple Car Rental web application that does all basic transactions
Actively involved in every aspect of application development.
JSP
Servlet
Bootstrap
Java
Developed an application to analyze performance of solid state drives by performing various kind of workloads and presented the analysis in UI.
C
FIO
Java
Netbeans Remote Procedures
+18178290923


MaxPooling1D
keras.layers.pooling.MaxPooling1D(pool_length=2, stride=None, border_mode='valid')
Max pooling operation for temporal data.
Input shape
3D tensor with shape: (samples, steps, features)
.
Output shape
3D tensor with shape: (samples, downsampled_steps, features)
.
Arguments
- pool_length: size of the region to which max pooling is applied
- stride: integer, or None. factor by which to downscale.
2 will halve the input.
If None, it will default to
pool_length
. - border_mode: 'valid' or 'same'.
- Note: 'same' will only work with TensorFlow for the time being.
MaxPooling2D
keras.layers.pooling.MaxPooling2D(pool_size=(2, 2), strides=None, border_mode='valid', dim_ordering='default')
Max pooling operation for spatial data.
Arguments
- pool_size: tuple of 2 integers, factors by which to downscale (vertical, horizontal). (2, 2) will halve the image in each dimension.
- strides: tuple of 2 integers, or None. Strides values.
If None, it will default to
pool_size
. - border_mode: 'valid' or 'same'.
- Note: 'same' will only work with TensorFlow for the time being.
- dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 3.
It defaults to the
image_dim_ordering
value found in your Keras config file at~/.keras/keras.json
. If you never set it, then it will be "tf".
Input shape
4D tensor with shape:
(samples, channels, rows, cols)
if dim_ordering='th'
or 4D tensor with shape:
(samples, rows, cols, channels)
if dim_ordering='tf'.
Output shape
4D tensor with shape:
(nb_samples, channels, pooled_rows, pooled_cols)
if dim_ordering='th'
or 4D tensor with shape:
(samples, pooled_rows, pooled_cols, channels)
if dim_ordering='tf'.
MaxPooling3D
keras.layers.pooling.MaxPooling3D(pool_size=(2, 2, 2), strides=None, border_mode='valid', dim_ordering='default')
Max pooling operation for 3D data (spatial or spatio-temporal).
Arguments
- pool_size: tuple of 3 integers, factors by which to downscale (dim1, dim2, dim3). (2, 2, 2) will halve the size of the 3D input in each dimension.
- strides: tuple of 3 integers, or None. Strides values.
- border_mode: 'valid' or 'same'.
- dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 4.
It defaults to the
image_dim_ordering
value found in your Keras config file at~/.keras/keras.json
. If you never set it, then it will be "tf".
Input shape
5D tensor with shape:
(samples, channels, len_pool_dim1, len_pool_dim2, len_pool_dim3)
if dim_ordering='th'
or 5D tensor with shape:
(samples, len_pool_dim1, len_pool_dim2, len_pool_dim3, channels)
if dim_ordering='tf'.
Output shape
5D tensor with shape:
(nb_samples, channels, pooled_dim1, pooled_dim2, pooled_dim3)
if dim_ordering='th'
or 5D tensor with shape:
(samples, pooled_dim1, pooled_dim2, pooled_dim3, channels)
if dim_ordering='tf'.
AveragePooling1D
keras.layers.pooling.AveragePooling1D(pool_length=2, stride=None, border_mode='valid')
Average pooling for temporal data.
Arguments
- pool_length: factor by which to downscale. 2 will halve the input.
- stride: integer, or None. Stride value.
If None, it will default to
pool_length
. - border_mode: 'valid' or 'same'.
- Note: 'same' will only work with TensorFlow for the time being.
Input shape
3D tensor with shape: (samples, steps, features)
.
Output shape
3D tensor with shape: (samples, downsampled_steps, features)
.
AveragePooling2D
keras.layers.pooling.AveragePooling2D(pool_size=(2, 2), strides=None, border_mode='valid', dim_ordering='default')
Average pooling operation for spatial data.
Arguments
- pool_size: tuple of 2 integers, factors by which to downscale (vertical, horizontal). (2, 2) will halve the image in each dimension.
- strides: tuple of 2 integers, or None. Strides values.
If None, it will default to
pool_size
. - border_mode: 'valid' or 'same'.
- Note: 'same' will only work with TensorFlow for the time being.
- dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 3.
It defaults to the
image_dim_ordering
value found in your Keras config file at~/.keras/keras.json
. If you never set it, then it will be "tf".
Input shape
4D tensor with shape:
(samples, channels, rows, cols)
if dim_ordering='th'
or 4D tensor with shape:
(samples, rows, cols, channels)
if dim_ordering='tf'.
Output shape
4D tensor with shape:
(nb_samples, channels, pooled_rows, pooled_cols)
if dim_ordering='th'
or 4D tensor with shape:
(samples, pooled_rows, pooled_cols, channels)
if dim_ordering='tf'.
AveragePooling3D
keras.layers.pooling.AveragePooling3D(pool_size=(2, 2, 2), strides=None, border_mode='valid', dim_ordering='default')
Average pooling operation for 3D data (spatial or spatio-temporal).
Arguments
- pool_size: tuple of 3 integers, factors by which to downscale (dim1, dim2, dim3). (2, 2, 2) will halve the size of the 3D input in each dimension.
- strides: tuple of 3 integers, or None. Strides values.
- border_mode: 'valid' or 'same'.
- dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 4.
It defaults to the
image_dim_ordering
value found in your Keras config file at~/.keras/keras.json
. If you never set it, then it will be "tf".
Input shape
5D tensor with shape:
(samples, channels, len_pool_dim1, len_pool_dim2, len_pool_dim3)
if dim_ordering='th'
or 5D tensor with shape:
(samples, len_pool_dim1, len_pool_dim2, len_pool_dim3, channels)
if dim_ordering='tf'.
Output shape
5D tensor with shape:
(nb_samples, channels, pooled_dim1, pooled_dim2, pooled_dim3)
if dim_ordering='th'
or 5D tensor with shape:
(samples, pooled_dim1, pooled_dim2, pooled_dim3, channels)
if dim_ordering='tf'.
GlobalMaxPooling1D
keras.layers.pooling.GlobalMaxPooling1D()
Global max pooling operation for temporal data.
Input shape
3D tensor with shape: (samples, steps, features)
.
Output shape
2D tensor with shape: (samples, features)
.
GlobalAveragePooling1D
keras.layers.pooling.GlobalAveragePooling1D()
Global average pooling operation for temporal data.
Input shape
3D tensor with shape: (samples, steps, features)
.
Output shape
2D tensor with shape: (samples, features)
.
GlobalMaxPooling2D
keras.layers.pooling.GlobalMaxPooling2D(dim_ordering='default')
Global max pooling operation for spatial data.
Arguments
- dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 3.
It defaults to the
image_dim_ordering
value found in your Keras config file at~/.keras/keras.json
. If you never set it, then it will be "tf".
Input shape
4D tensor with shape:
(samples, channels, rows, cols)
if dim_ordering='th'
or 4D tensor with shape:
(samples, rows, cols, channels)
if dim_ordering='tf'.
Output shape
2D tensor with shape:
(nb_samples, channels)
GlobalAveragePooling2D
keras.layers.pooling.GlobalAveragePooling2D(dim_ordering='default')
Global average pooling operation for spatial data.
Arguments
- dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 3.
It defaults to the
image_dim_ordering
value found in your Keras config file at~/.keras/keras.json
. If you never set it, then it will be "tf".
Input shape
4D tensor with shape:
(samples, channels, rows, cols)
if dim_ordering='th'
or 4D tensor with shape:
(samples, rows, cols, channels)
if dim_ordering='tf'.
Output shape
2D tensor with shape:
(nb_samples, channels)


On Monster Games' first two self-published titles we found ourselves without an audio designer. So in addition to my programming tasks, I was responsible for all of the sound effects design on these games (engines, exhaust, tire rolls, skids, collisions and UI).
It was quite challenging as I have no experience or training in this area. Still, as a hobbyist musician, I know my way around audio tools and am at least passingly familiar with many of the core concepts. I'm pretty happy with how these games sound, all things considered.
On the code side I was responsible for an extensive rewrite of the race-state-driven voice-over system to allow it to act as an announcer or a spotter depending upon the game's needs. I also continued to support the art department with tools for rapid track construction, including a tool for planting randomized signage along arbitrary quartic bezier paths over the terrain.
These games were built in Unity for PC, PS4, and Xbox One
My primary responsibility for NH4 was the integration of FMOD as our new sound engine. This included writing a wrapper over the FMOD API to allow it to easily plug into our existing audio calls. I also supported the audio designer with features and tools and worked with Javascript in the FMOD Studio Editor scripting environment.
I also supported the art department with tools, including a fence builder that allows the track artists to easily place customizable fences that follow the contour of the terrain.
This game was built in Unity for PC, PS4, and Xbox One
With the Nintendo decade at Monster Games having come to a close in 2015, these two games marked the end of my tenure as a level designer and my return to programming full time.
Nascar Heat Evolution was my first exposure to Unity, the C# language, and shader programming. I wrote the vehicle damage system (that crumples the vehicle mesh in a collision) and collaborated on the design and implementation of our new UI system, among other things.
These games were built in Unity for PC, PS4, and Xbox One
It's incredible to have my name associated with Xenoblade, even in some small way. It's one of the best JRPGs I've ever played. There was little to no game design on this title (it was a straight port to 3DS), but the dual-screen nature of the target platform meant an extensive redesign of the UI and seeing as how this is a fairly traditional RPG, there was a ton of work to be done.
I was involved in much of the redesign. However, my primary responsibility was writing a UI editor in Java for the team to use. It was slick and powerful and one of the things I'm most proud of over my career so far.
After our success designing new levels for the 3DS port of Donkey Kong Country Returns, we collaborated with Retro Studios to help them finish Donkey Kong Country: Tropical Freeze for the Wii U.
The design team at Monster Games spent about a month and a half at Retro Studios in Austin Texas. We learned their new tools for DKCR:TF level design.
It was pretty intense, but also super fun and satisfying. I also found that I don't mind working off-site for an extended period of time if needed.
Baobab Bonanza was an intriguing level to work on. The core gimmicks came as a (somewhat) vague request from Nintendo: rolling nuts and "tippy flower platforms." I'm particularly proud of the giant nut set-piece at the end of the level.
Current Capers was a collaborative effort on the part of the whole MGI design team. I designed the electrified tentacles and several of the rooms and sequences in this level.
Spinning Spines was my first level for DKCR: Tropical Freeze. I think the giant spinning cylinders are cool, and getting blasted down the center of the big one into the lava pools is pretty exciting!
Of all the levels I've designed, I think I'm the proudest of this one. We were under the gun at the end of the project, and my colleague Todd and I managed to put this level together in record time... and it turned out to be one of our best!
DKCR3D was the first really big-name game I worked on. It was a port of the Wii version of Donkey Kong Country Returns to the Nintendo 3DS platform.
I was on the design team for this one. We added a new 9th world with eight new levels and redesigned the UI to work on the 3DS' dual screens.
Monster Games' first Donkey Kong level. Crushing Columns was a collaborative effort with one of the other designers. I'm very proud of the primary gimmick (the tracked platform that tips right and left) and the sequence at the end where the columns come crashing down on the platforms.
I was thinking Indiana Jones when I made this level. The walls are closing in! You've got to move fast to stay ahead of the spikes!
This is a great level, however it's not my design. I was responsible for the complex network of metronomes and reset logic that keeps all of the moving platforms in lock-step with the beat of the music.
Pilot Wings Resort was a launch title for the Nintendo 3DS. It was fantastic to get to use the 3DS prototype hardware before Nintendo even announced the system. I designed around 1/3 of the levels for this game and worked on UI design as well.
ExciteBike World Rally was a downloadable game for Nintendo WiiWare. It is essentially a reboot of the original Excitebike with all new levels, many of which I designed.
This game was so much fun to work on because I still have vivid memories of playing the Excitebike arcade machine at a local pizza joint when I was a little kid.
The environments are based on the worlds from Excite Truck and Excitebots, but the game is pure, old-school Excitebike.
What a totally bizarre game this is. Animal shaped vehicles that turn into robots, huge air, crazy tricks, weird in-race minigames, a high-speed multiplayer poker game, unlockable costumes for the vehicles...designing levels for this game was super fun and kinda surreal.
This was my first project at Monster Games, and the first of many Nintendo games I worked on. I joined the team near the end of this project so my design contributions are minimal (rings and token placement) but I did a lot of QA work on this one.
What started as my first Unity experiment ended up turning into an actual product with some friends' help. An old-school arcade-inspired shooter with juicy pixel art for mobile (iOS, Android).
We finished it, and it was available on the mobile stores for a while, but since we are pretty clueless about marketing and advertising, it just kinda fizzled out.
I took some time off from Monster Games in 2018 and worked a remote, part-time job at CogReps Inc. under their lead programmer, who is also an old friend of mine. I did a lot of UI programming and design on this project.
Close Combat 4 was the first game of my career. I was hired as a junior programmer but worked in the QA department on CC4 since it was close to being completed when I joined the Atomic Games team.
After this, I worked as a programmer on the Hammer's Slammers project. Unfortunately, Hammer's Slammers was cancelled in 2000, and all Atomic Games staff were laid off except three executives.