15 Tree-based models
The models up to this point have been linear. This means that \(Y\) changes gradually as \(X\) changes.
Tree-based models allow for abrupt changes in \(Y\).
15.1 Decision Trees
Decision trees can be used for either classification or regression problems. The model structure is a series of yes/no questions. Depending on how each observation answers these questions, a prediction is made.
The below example shows how a single tree can predict health claims.
- For non-smokers, the predicted annual claims are 8,434. This represents 80% of the observations
- For smokers with a
bmi
of less than 30, the predicted annual claims are 21,000. 10% of patients fall into this bucket. - For smokers with a
bmi
of more than 30, the prediction is 42,000. This bucket accounts for 11% of patients.
We can cut the data set up into these groups and look at the claim costs. From this grouping, we can see that smoker
is the most important variable as the difference in average claims is about 20,000.
| smoker | bmi_30 | mean_claims | percent |
|---|---|---|---|
| no | bmi < 30 | $7,155.75 | 0.34 |
| no | bmi >= 30 | $8,438.77 | 0.47 |
| yes | bmi < 30 | $23,332.61 | 0.07 |
| yes | bmi >= 30 | $42,111.82 | 0.12 |
This was a very simple example because there were only two variables. If we have more variables, the tree will get large very quickly. This will result in overfitting; there will be good performance on the training data but poor performance on the test data.
The step-by-step process of building a tree is
Step 1: Find the best predictor-split-point combination
This variable could be any one of age
, children
, charges
, sex
, smoker
, age_bucket
, bmi
, or region
.
The split point which best separates observations out based on the value of \(y\). A good split is one where the \(y\)’s are very different. * **
In this case, smoker
was chosen. Then we can only split this in one way: smoker = "yes"
or smoker = "no"
. Notice that although this is a categorical variable, the tree does not need to binanize the variables. Instead, like the table above shows, the data gets partitioned by the categories directly.
Then for each of these groups, smokers and non-smokers, find the next variable and split point which best separates out the claims. In this case, for no-smokers, age
was chosen. To find the best cut point of age
, look at all possible age cut points from 18, 19, 20, 21, …, 64 and choose the one which best separates the data.
There are three ways of deciding where to split
- Entropy (aka, information gain)
- Gini
- Classification error
Of these, only the first two are commonly used. The exam is not going to ask you to calculate either of these. Just know that neither method will work better on all data sets, and so the best practice is to test both and compare the performance.
Step 2: Continue doing this until a stopping criteria is reached. For example, the minimum number of observations is 5 or less.
As you can see, this results in a very deep tree.
tree <- rpart(formula = charges ~ ., data = health_insurance,
control = rpart.control(cp = 0.003))
rpart.plot(tree, type = 3)
Step 3: Apply cost comlexity pruning to simplify the tree
Intuitively, we know that the above model would perform poorly due to overfitting. We want to make it simpler by removing nodes. This is very similar to how in linear models we reduce complexity by reducing the number of coefficients.
A measure of the depth of the tree is the complexity. A simple way of measuring this from the number of terminal nodes, called \(|T|\). In the above example, \(|T| = 8\). The amount of penalization is controlled by \(\alpha\). This is very similar to \(\lambda\) in the Lasso.
Intuitively, only looking at the number of nodes by itself is too simple because not all data sets will have the same characteristics such as \(n\), \(p\), the number of categorical variables, correlations between variables, and so fourth. In addition, if we just looked at the error (squared error in this case) we would overfit very easily. To address this issue, we use a cost function which takes into account the error as well as \(|T|\).
To calculate the cost of a tree, number the terminal nodes from \(1\) to \(|T|\), and let the set of observations that fall into the \(mth\) bucket be \(R_m\). Then add up the squared error over all terminal nodes to the penalty term.
\[ \text{Cost}_\alpha(T) = \sum_{m=1}^{|T|} \sum_{R_m}(y_i - \hat{y}_{Rm})^2 + \alpha |T| \]
Step 4: Use cross-validation to select the best alpha
The cost is controlled by the CP
parameter. In the above example, did you notice the line rpart.control(cp = 0.003)
? This is telling rpart
to continue growing the tree until the CP reaches 0.003. At each subtree, we can measure the cost CP
as well as the cross-validation error xerror
.
This is stored in the cptable
tree <- rpart(formula = charges ~ ., data = health_insurance,
control = rpart.control(cp = 0.0001))
cost <- tree$cptable %>%
as_tibble() %>%
select(nsplit, CP, xerror)
cost %>% head()
## # A tibble: 6 x 3
## nsplit CP xerror
## <dbl> <dbl> <dbl>
## 1 0 0.620 1.00
## 2 1 0.144 0.382
## 3 2 0.0637 0.238
## 4 3 0.00967 0.175
## 5 4 0.00784 0.169
## 6 5 0.00712 0.163
As more splits are added, the cost continues to decrease, reaches a minimum, and then begins to increase.
To optimize performance, choose the number of splits which has the lowest error. Often, though, the goal of using a decision tree is to create a simple model. In this case, we can err or the side of a lower nsplit
so that the tree is shorter and more interpretable. All of the questions on so far have only used decision trees for interpretability, and a different model method has been used when predictive power is needed.
Once we have selected \(\alpha\), the tree is pruned. This table below shows 6 different trees. The xerror
column is the missclassification error. The rel error
is the relative error, which is the missclassification error divided by its smallest value. This rescales xerror
so that the tree with the smallest error is given a rel error
of 1.00.
## # A tibble: 6 x 4
## nsplit CP xerror `rel error`
## <dbl> <dbl> <dbl> <dbl>
## 1 0 0.620 1.00 1
## 2 1 0.144 0.382 0.380
## 3 2 0.0637 0.238 0.236
## 4 3 0.00967 0.175 0.173
## 5 4 0.00784 0.169 0.163
## 6 5 0.00712 0.163 0.155
The SOA may give you code to find the lowest CP value such as below. You could always find this value yourself by inspecting the CP table and choosing the value of CP
which has the lowest xerror
.
To make a simple tree, there are a few options
- Set the maximum depth of a tree with
maxdepth
- Manually set
cp
to be higher - Use fewer input variables and avoid categories with many levels
- Force a high number of minimum observations per terminal node with
minbucket
For instance, using these suggestions allows for a simpler tree to be fit.
library(caret)
set.seed(42)
index <- createDataPartition(y = health_insurance$charges,
p = 0.8, list = F)
train <- health_insurance %>% slice(index)
test <- health_insurance %>% slice(-index)
simple_tree <- rpart(formula = charges ~ .,
data = train,
control = rpart.control(cp = 0.0001,
minbucket = 200,
maxdepth = 10))
rpart.plot(simple_tree, type = 3)
We evaluate the performance on the test set. Because the target variable charges
is highly skewed, we use the Root Mean Squared Log Error (RMSLE). We see that the complex tree has the best (lowest) error, but also has 8 terminal nodes. The simple tree with only three terminal nodes has worse (higher) error, but this is still an improvement over the mean prediction.
tree_pred <- predict(tree, test)
simple_tree_pred <- predict(simple_tree, test)
get_rmsle <- function(y, y_hat){
sqrt(mean((log(y) - log(y_hat))^2))
}
get_rmsle(test$charges, tree_pred)
## [1] 0.3920546
## [1] 0.5678457
## [1] 0.9996513
15.1.1 Example: SOA PA 6/18/2020, Task 6
Describe what pruning does and why it might be considered it for this business problem.
Construct an unpruned regression tree using the code provided.
Review the complexity parameter table and plot for this tree. State the optimal complexity parameter and the number of leaves that will result if the tree is pruned using that value.
Prune the tree using a complexity parameter that will result in eight leaves. If eight is not a possible option, select the largest number less than eight that is possible.
Calculate and compare the Pearson goodness-of-fit statistic on the test set for both trees (original and pruned).
Interpret the entire pruned tree (all leaves) in the context of the business problem.
15.1.2 Advantages and disadvantages
Advantages
- Easy to interpret
- Performs variable selection
- Categorical variables do not require binarization in order for each level to be used as a separate predictor
- Captures non-linearities
- Captures interaction effects
- Handles missing values
Disadvantages
- Is a “weak learner” because of low predictive power
- Does not work on small data sets
- Is often a simplification of the underlying process because all observations at terminal nodes have equal predicted values
- High variance (which can be alleviated with stricter parameters) leads the “easy to interpret results” to change upon retraining Unable to predict beyond the range of the training data for regression (because each predicted value is an average of training samples)
| Readings | |
|---|---|
| ISLR 8.1.1 Basics of Decision Trees | |
| ISLR 8.1.2 Classification Trees | |
| rpart Documentation (Optional) |
15.2 Ensemble learning
The “wisdom of crowds” says that often many are smarter than the few. In the context of modeling, the models which we have looked at so far have been single guesses; however, often the underlying process is more complex than any single model can explain. If we build separate models and then combine them, known as ensembling, performance can be improved. Instead of trying to create a single perfect model, many simple models, known as weak learners are combined into a meta-model.
The two main ways that models are combined are through bagging and boosting.
15.2.1 Bagging
To start, we create many “copies” of the training data by sampling with replacement. Then we fit a simple model, typically a decision tree or linear model, to each of the data sets. Because each model is looking at different areas of the data, the predictions are different. The final model is a weighted average of each of the individual models.
15.2.2 Boosting
Boosting always uses the original training data and iteratively fits models to the error of the prior models. These weak learners are ineffective by themselves but powerful when added together. Unlike with bagging, the computer must train these weak learners sequentially instead of in parallel.
15.3 Random Forests
A random forest is the most common example of bagging. As the name implies, a forest is made up of trees. Seperate trees are fit to sampled data sets. For random forests, there is one minor modification: in order to make each model even more different, each tree selects a random subset of variables.
If we had to explain why a random forest works in three steps, they would be:
- Assume that the underlying process, \(Y\), has some signal within the data \(\mathbf{X}\).
- Introduce randomness (variance) to capture the signal.
- Remove the variance by taking an average.
When using only a single tree, there can only be as many predictions as there are terminal nodes. In a random forest, predictions can be more granular due to the contribution of each of the trees.
The below graph illustrates this. A single tree (left) has stair-like, step-wise predictions whereas a random forest is free to predict any value. The color represents the predicted value (yellow = highest, black = lowest).
Unlike decision trees, random forest trees do not need to be pruned. This is because overfitting is less of a problem: if one tree overfits, there are other trees which overfit in other areas to compensate.
In most applications, only the mtry
parameter, which controls how many variables to consider at each split, needs to be tuned. Tuning the ntrees
parameter is not required; however, the SOA may still ask you to.
15.3.1 Example
Using the basic randomForest
package we fit a model with 500 trees.
This expects only numeric values. We create dummy (indicator) columns.
rf_data <- health_insurance %>%
sample_frac(0.2) %>%
mutate(sex = ifelse(sex == "male", 1, 0),
smoker = ifelse(smoker == "yes", 1, 0),
region_ne = ifelse(region == "northeast", 1,0),
region_nw = ifelse(region == "northwest", 1,0),
region_se = ifelse(region == "southeast", 1,0),
region_sw = ifelse(region == "southwest", 1,0)) %>%
select(-region)
rf_data %>% glimpse(50)
## Observations: 268
## Variables: 10
## $ age <dbl> 42, 44, 31, 36, 64, 28, 45,...
## $ sex <dbl> 1, 1, 1, 1, 1, 0, 1, 1, 0, ...
## $ bmi <dbl> 26.125, 39.520, 27.645, 34....
## $ children <dbl> 2, 0, 2, 2, 0, 3, 0, 0, 0, ...
## $ smoker <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 1, ...
## $ charges <dbl> 7729.646, 6948.701, 5031.27...
## $ region_ne <dbl> 1, 0, 1, 0, 1, 0, 0, 0, 0, ...
## $ region_nw <dbl> 0, 1, 0, 0, 0, 1, 1, 0, 1, ...
## $ region_se <dbl> 0, 0, 0, 1, 0, 0, 0, 1, 0, ...
## $ region_sw <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
library(caret)
set.seed(42)
index <- createDataPartition(y = rf_data$charges,
p = 0.8, list = F)
train <- rf_data %>% slice(index)
test <- rf_data %>% slice(-index)
We again use RMSLE. This is lower (better) than a model that uses the average as a baseline.
pred <- predict(rf, test)
get_rmsle <- function(y, y_hat){
sqrt(mean((log(y) - log(y_hat))^2))
}
get_rmsle(test$charges, pred)
## [1] 0.5252518
## [1] 1.118947
15.3.2 Variable Importance
Variable importance is a way of measuring how each variable contributes to the overall model’s performance. For single decision trees, variable “higher up” in the tree have greater influence. Statistically, there are two ways of measuring this:
Look at the mean reduction in accuracy when the variable is randomly permuted verses using the actual values from the data. This is done with
type = 1
(default).Use the total decrease in node impurities from splitting on the variable, averaged over all trees. For classification, the node impurity is measured by the Gini index; for regression, it is measured by the residual sum of squares \(\text{RSS}\). This is
type = 2
.
smoker
, bmi
, and age
are the most importance predictors of charges. As you can imagine, variable importance is a highly useful tool for building models. We could use this to test out newly engineered features, or perform feature selection by taking the top-n features and use them in a different model. Random forests can handle very high dimensional data which allows for many tests to be run at once.
15.3.3 Partial dependence
We know which variables are important, but what about the direction of the change? In a linear model we would be able to just look at the sign of the coefficient. In tree-based models, we have a tool called partial dependence. This attempts to measure the change in the predicted value by taking the average \(\hat{\mathbf{y}}\) after removing the effects of all other predictors.
Although this is commonly used for trees, this approach is model-agnostic in that any model could be used.
Take a model of two predictors, \(\hat{\mathbf{y}} = f(\mathbf{X}_1, \mathbf{X_2})\). For simplicity, say that \(f(x_1, x_2) = 2x_1 + 3x_2\).
The data looks like this
## # A tibble: 4 x 3
## x1 x2 f
## <dbl> <dbl> <dbl>
## 1 1 3 11
## 2 1 4 14
## 3 2 5 19
## 4 2 6 22
Here is the partial dependence of x1
on to f
.
## # A tibble: 2 x 2
## x1 f
## <dbl> <dbl>
## 1 1 12.5
## 2 2 20.5
This method of using the mean is know as the Monte Carlo method. There are other methods for partial dependence that are not on the syllabus.
For the Random Forest, this is done with pdp::partial()
.
library(pdp)
bmi <- pdp::partial(rf, pred.var = "bmi",
grid.resolution = 15) %>%
autoplot() + theme_bw()
age <- pdp::partial(rf, pred.var = "age",
grid.resolution = 15) %>%
autoplot() + theme_bw()
ggarrange(bmi, age)
15.3.4 Advantages and disadvantages
Advantages
- Resilient to overfitting due to bagging
- Only one parameter to tune (mtry, the number of features considered at each split)
- Very good a multi-class prediction
- Nonlinearities
- Interaction effects
- Handles missing data
- Deals with unbalanced after over/undersampling
Disadvantages
- Does not work on small data sets
- Weaker performance than other methods (GBM, NN)
- Unable to predict beyond training data for regression
| Readings | |
|---|---|
| ISLR 8.2.1 Bagging | |
| ISLR 8.1.2 Random Forests |
15.4 Gradient Boosted Trees
Another ensemble learning method is gradient boosting, also known as the Gradient Boosted Machine (GBM). This is one of the most widely-used and powerful machine learning algorithms that is in use today.
Before diving in to the gradient boosting, understanding the AdaBoost algorithm is helpful.
15.4.1 Gradient Boosting
15.4.2 Notation
Start with an initial model, which is just a constant prediction of the mean.
\[f = f_0(\mathbf{x_i}) = \frac{1}{n}\sum_{i=1}^ny_i\]
Then we update the target (what the model is predicting) by subtracting off the previously predicted value.
\[ \hat{y_i} \leftarrow y_i - f_0(\mathbf{x_i})\]
This \(\hat{y_i}\) is called the residual. In our example, instead of predicting charges
, this would be predicting the residual of \(\text{charges}_i - \text{Mean}(\text{charges})\). We now use this model for the residuals to update the prediction.
If we updated each prediction with the prior residual directly, the algorithm would be unstable. To make this process more gradual, we use a learning rate parameter.
At step 2, we have
\[f = f_0 + \alpha f_1\]
Then we go back and fit another weak learner to this residual and repeat.
\[f = f_0 + \alpha f_1 + \alpha f_2\]
We then iterate through this process hundreds or thousands of times, slowly improving the prediction.
Because each new tree is fit to residuals instead of the response itself, the process continuously improves the prediction. As the prediction improves, the residuals get smaller and smaller. In random forests, or other bagging algorithms, the model performance is more limited by the individual trees because each only contributes to the overall average. The name is gradient boosting because the residuals are an approximation of the gradient, and gradient descent is how the loss functions are optimized.
Similarly to how GLMs can be used for classification problems through a logit transform (aka logistic regression), GBMs can also be used for classification.
15.4.3 Parameters
For random forests, the individual tree parameters do not get tuned. For GBMs, however, these parameters can make a significant difference in model performance.
Boosting parameters:
n.trees
: Integer specifying the total number of trees to fit. This is equivalent to the number of iterations and the number of basis functions in the additive expansion. Default is 100.shrinkage
: a shrinkage parameter applied to each tree in the expansion. Also known as the learning rate or step-size reduction; 0.001 to 0.1 usually work, but a smaller learning rate typically requires more trees. Default is 0.1.
Tree parameters:
interaction.depth
: Integer specifying the maximum depth of each tree (i.e., the highest level of variable interactions allowed). A value of 1 implies an additive model, a value of 2 implies a model with up to 2-way interactions, etc. Default is 1.n.minobsinnode
: Integer specifying the minimum number of observations in the terminal nodes of the trees. Note that this is the actual number of observations, not the total weight.
GBMs are easy to overfit, and the parameters need to be carefully tuned using cross-validation. In the Examples section we go through how to do this.
Tip: Whenever fitting a model, use ?model_name
to get the documentation. The parameters below are from ?gbm
.
15.4.4 Example
We fit a gbm below without tuning the parameters for the sake of example.
library(gbm)
gbm <- gbm(charges ~ ., data = train,
n.trees = 100,
interaction.depth = 2,
n.minobsinnode = 50,
shrinkage = 0.1)
## Distribution not specified, assuming gaussian ...
## [1] 1.052716
## [1] 1.118947
15.4.5 Advantages and disadvantages
This exam covers the basics of GBMs. There are many variations of GBMs not covered in detail such as xgboost
.
Advantages
- High prediction accuracy
- Shown to work empirically well on many types of problems
- Nonlinearities, interaction effects, resilient to outliers, corrects for missing values
- Deals with class imbalance directly by weighting observations
Disadvantages
- Requires large sample size
- Longer training time
- Does not detect linear combinations of features. These must be engineered Can overfit if not tuned correctly
| Readings | |
|---|---|
| ISLR 8.2.3 Boosting |
15.5 Exercises
Run this code on your computer to answer these exercises.
15.5.1 1. RF tuning with caret
The best practice of tuning a model is with cross-validation. This can only be done in the caret
library. If the SOA asks you to use caret
, they will likely ask you a question related to cross validation as below.
An actuary has trained a predictive model and chosen the best hyperparameters, cleaned the data, and performed feature engineering. They have one problem, however: the error on the training data is far lower than on new, unseen test data. Read the code below and determine their problem. Find a way to lower the error on the test data without changing the model or the data. Explain the rational behind your method.
set.seed(42)
#Take only 250 records
#Uncomment this when completing this exercise
data <- health_insurance %>% sample_n(250)
index <- createDataPartition(
y = data$charges, p = 0.8, list = F) %>%
as.numeric()
train <- health_insurance %>% slice(index)
test <- health_insurance %>% slice(-index)
control <- trainControl(
method='boot',
number=2,
p = 0.2)
tunegrid <- expand.grid(.mtry=c(1,3,5))
rf <- train(charges ~ .,
data = train,
method='rf',
tuneGrid=tunegrid,
trControl=control)
pred_train <- predict(rf, train)
pred_test <- predict(rf, test)
get_rmse <- function(y, y_hat){
sqrt(mean((y - y_hat)^2))
}
get_rmse(pred_train, train$charges)
get_rmse(pred_test, test$charges)
15.5.2 2. Tuning a GBM with caret
If the SOA asks you to tune a GBM, they will need to give you starting hyperparameters which are close to the “best” values due to how slow the Prometric computers are. Another possibility is that they pre-train a GBM model object and ask that you use it.
This example looks at 135 combinations of hyper parameters.
set.seed(42)
index <- createDataPartition(y = health_insurance$charges,
p = 0.8, list = F)
#To make this run faster, only take 50% sample
df <- health_insurance %>% sample_frac(0.50)
train <- df %>% slice(index)
test <- df %>% sample_frac(0.05)%>% slice(-index)
tunegrid <- expand.grid(
interaction.depth = c(1,5, 10),
n.trees = c(50, 100, 200, 300, 400),
shrinkage = c(0.5, 0.1, 0.0001),
n.minobsinnode = c(5, 30, 100)
)
nrow(tunegrid)
control <- trainControl(
method='repeatedcv',
number=5,
p = 0.8)
gbm <- train(charges ~ .,
data = train,
method='gbm',
tuneGrid=tunegrid,
trControl=control,
#Show detailed output
verbose = FALSE
)
The output shows the RMSE for each of the 135 models tested.
(Part 1 of 3)
Identify the hyperpameter combination that has the lowest training error.
(Part 2 of 3)
- Suppose that the optimization measure was RMSE. The below table shows the results from three models. Explain why some sets of parameters have better RMSE than the others.
results <- gbm$results %>% arrange(RMSE)
top_result <- results %>% slice(1)%>% mutate(param_rank = 1)
tenth_result <- results %>% slice(10)%>% mutate(param_rank = 10)
twenty_seventh_result <- results %>% slice(135)%>% mutate(param_rank = 135)
rbind(top_result, tenth_result, twenty_seventh_result) %>%
select(param_rank, 1:5)
- The partial dependence of
bmi
ontocharges
makes it appear as ifcharges
increases monotonically asbmi
increases.
However, when we add in the ice
curves, we see that there is something else going on. Explain this graph. Why are there two groups of lines?


--- layout: archive title: Zulip Chat Archive permalink: /stream/116395-maths/topic/Nuances.20regarding.20naturality.html ---
https://mathoverflow.net/questions/244131/nuances-regarding-naturality?noredirect=1&lq=1
Does Lean have a good answer to this question? My understanding is that the OP is trying to define data which involves an uncomputable choice of some other data (and it's a theorem that such a choice can always be made in at least one way) and then a proof that the data we care about is independent of this uncomputable choice.
Is the function that sends a vector space to the cardinal corresponding to its dimension any "better" in any way than the function that sends a vector space to a basis which was chosen using the axiom of choice?
Perhaps I'm missing something, but the dimension function is defined using the "choose-a-basis" function, right?
I ran into this when I was working on the rank function for matroids (which is a generalization of dimension for f.d. vector spaces); even with unique existence, you still have to apply some form of choice to define the actual nat.
Yes. The question is whether the added nuance of the proof that the output is independent of the choice can be expressed in Lean. A mathematician might argue that they hadn't "seriously" used choice, or something. I was wondering if there was anything in this.
It could still be done computably, using trunc
, instead of exists
, and quot.lift
instead of choice.
The dimension function can be defined using only "unique choice" nonempty a -> (\all x y : a, x = y) -> a
. This is just as noncomputable as full choice but philosophically less problematic (at least to me) because the type of the "unique choice" constant is a subsingleton.
Another formulation is nonempty a -> trunc a
, yes
At the time I ended up throwing in an encodable
instance. I'll have to look into trunc
now that I know a little more about it though.
The "pick a basis" function is different because its value depends on the interpretation of the choice
constant
What's nonempty a -> trunc a
? I see nonempty_of_trunc
in mathlib but not the other way around. Is this because in lean's foundations there's no unique choice? To define the dimension function in lean, am I right that you could only do it by returning the cardinality of "pick a basis"? Well-definedness would be proven and used separately I suppose.
choice
, then trunc.mk
Lean's core library only has the axiom choice
, and derives all the other classical principles from it. So in this setup you can't make fine distinctions between things like using choice and only using unique choice. However, you could imagine adding unique choice (and LEM) as separate axioms.
You could also add the "axiom of choice" (which is a Prop) as a separate axiom.
Then you could define the dimension function using only the "axiom of choice" (to prove nonempty (basis V)
) and "unique choice" (to extract the dimension)--in order to do this you have to prove that every basis has the same cardinality
Both of these axioms are subsingletons, so you can conclude that the dimension of a vector space doesn't depend on the interpretation of choice
or on any other "arbitrary choices".
You cannot define the "pick a basis" function this way
is it possible to define trunc (basis V)
computably?
How are you given V
?
k : Type u V : Type v _inst_1 : field k _inst_2 : vector_space k V
@Kenny Lau providing a truncated basis could be part of the definition of finite dimensional vector space.
For the infinite case you can't do it, but who cares when cardinals don't have decidable equality.
so essentially I'm asking for a term of the type \Pi (k : Type u) (V : Type v) [field k] [vector_space k V], trunc (basis k V)
Last updated: Apr 24 2020 at 19:02 UTC


| APHELIA(1) | General Commands Manual | APHELIA(1) |
aphelia
—
Alt+a
Alt+s
Alt+q
Alt+Return
Alt+d
Alt+Backspace
Alt+Left
⟨click
⟩Alt+Right
⟨click
⟩aphelia
utility exits 0 on success,
and >0 if an error occurs.
This manual page was written by Nuno Teixeira<EMAIL_ADDRESS>and Jarred Vardy<EMAIL_ADDRESS>| May 1, 2019 | Mac OS X 10.14 |


Notebooks
Story: Ssa ka Kumm (the eland's story)
Ssa ka Kumm (the eland's story)
Title
Ssa ka Kumm (the eland's story)
Collection
Summary
The hunting of eland and related ceremonies. There are many things the hunter must do to show respect for the eland, as it is a 'magic thing' and |kaggen (the Mantis) will try to revive the game and keep it from dying. The verso notes contain further details of these practices. Pages 5359v-5361v contains warnings about the casting of shadows (translated by Dorothea Bleek).
Comments
1) p.5316v: this story was told to Dia!kwain by his father (Xaa-ttin), 2) Date on p.5338: 26 September, 3) p.5341v: an explanatory note by Dia!kwain (12 December 1875) on the actions of |kaggen (the Mantis) and how he changes his appearance to make people afraid (like at 'Guy Fawkes'), 4) pp.5345v-5348v: see The Mantis and the hunting of eland, 5) p.5353 opp: (4 October 1875) the !num !num moth found in Bushmanland in trees (caught at Mowbray, 3 October), 6) pp.5359v-5361v contains warnings about the casting of shadows (translated by Dorothea Bleek), 7) p.5361v: the throwing of shadows; what occurs after striking the eland with its tail, 8) See also Further ceremonies in cutting up eland, 9) This story is found in Books V-17 and V-18
Contributors
Date
September 1875
Categories
Keywords
eland (its story or Ssa ka Kumm) , eland (and hunting observances) , eland (its magic powers) , eland (is feared and respected) , eland (lean) , eland (fat) , eland (and the scent of people) , eland (a description of the ceremony for cutting up its meat) , eland (beating with its tail) , eland (breaking wind and hiccoughing when eating its fat) , eland (and the |kaggen) , eland (prohibitions when hunting) , eland (and urination) , eland (and Ssa ka Kumm) , eland (the |kaggen tries to make it live) , eland (the ceremony for killing) , eland (hunting) , eland (killing) , eland (is a magic thing) , eland (is |kaggen's thing) , eland (crossing its spoor) , eland (the actions with the arrow used to shoot it) , eland (what is done when one has been shot) , man (who has shot an eland) , man (and hunting observances) , man (the ceremonies he performs) , man (the hut made for him) , man (his dress) , man (is helped by old men) , man (and Ssa ka Kumm) , man (does not cross spoor) , man (imitates the wounded eland) , man (and the |kaggen) , man (urinates) , Ssa ka Kumm (the eland's story) , Ssa ka Kumm (hunting observances) , Ssa ka Kumm (hunting |kaggen's things) , Ssa ka Kumm (ceremonies for killing eland) , magic powers (possed by the eland) , magic powers (and Ssa ka Kumm) , urination (and Ssa ka Kumm) , urination (by the hunter on the wounded eland) , hut (made for man who has shot an eland) , hut (and Ssa ka Kumm) , dress (worn by man who has shot an eland) , dress (and Ssa ka Kumm) , arrow (actions with one with which an eland has been shot) , arrow (and Ssa ka Kumm) , education (and Ssa ka Kumm) , education (and killing an eland) , education (of hunting observances) , teaching (and Ssa ka Kumm) , teaching (and killing an eland) , teaching (of hunting observances) , |kaggen (the Mantis) , |kaggen (and the eland) , |kaggen (and Ssa ka Kumm) , |kaggen (the eland is its thing) , |kaggen (its actions when an eland has been shot) , |kaggen (torments the hunter) , |kaggen (appears in other forms) , |kaggen (wants the eland to live) , hunting (and Ssa ka Kumm) , hunting (and killing an eland) , hunting (ceremonies for cutting up game) , hunting (and avoidance behaviour) , hunting (and respecting the game) , hunting (fat and lean game) , hunting (methods of cutting up game) , hunting (observances) , hunting (of eland) , hunting (and ceremonies for killing and cutting up eland) , hunting (of magic things) , hunting (and Ssa ka Kumm) , hunting (prohibitions relating to) , hunting (of |kaggen's things) , game (respecting) , game (cutting up) , game (lean and fat) , game (ceremonies performed for) , game (and hunting observances) , game (and Ssa ka Kumm) , moth (the !num !num) , shadows (the casting of) , shadows (prohibitions relating to) , name (of a moth) , respect (shown to |kaggen's or magic things) , respect (shown to the eland) , respect (and Ssa ka Kumm) , ceremony (for the cutting up of eland) , ceremony (and Ssa ka Kumm) , ceremony (for the successful hunting of eland)
Story Pages
5317-5353, 5354-5363


This page can be used to test Google Pay's pay.js
in
live environment. No payment will be processed.
View source.
This page shows the reliance of isReadyToPay's
existingPaymentMethodRequired
parameter on third-party
cookies. In a browser with third-party cookies disabled, the GPay button
below won't load, even if you are signed into Google and have a matching
payment method available.
To turn off third-party cookies in Chrome, visit chrome://settings/cookies and select "Block third-party cookies", then refresh this page.


s6
Software
skarnet.org
The s6-svdt program
s6-svdt prints the recorded death tally of a service, i.e. a list of the times
the process died, with the cause of death.
Interface
s6-svdt [ -S | -s ] [ -n maxlines ] servicedir
s6-svdt prints the contents of the recorded death tally of the service being
currently supervised at the servicedir
service directory, then exits 0.
For each recorded death, s6-svdt prints one line. This line contains the
following fields, separated with spaces:
- A TAI64N
timestamp .
- The word "signal" if the death was caused by a signal, or the word
"exitcode" if the death was a normal exit.
- The name of the signal that caused the death, or the exit code
of the process.
Options
- -S : print signal names. This is the default.
- -s : print signal numbers. The numerical value of the signal
will be printed instead of the signal name.
- -n maxlines : limit the output to at most
the latest maxlines deaths.
Exit codes
- 0: success
- 100: wrong usage
- 111: system call failed
Notes
- To obtain human-readable local time or GMT time instead of TAI64N timestamps,
simply pipe s6-svdt's output into s6-tai64nlocal.
- Process deaths are recorded up to a default maximum of 100. This default can
be modified via the max-death-tally file in the
service directory.


Preparation time
30 mins to 1 hour
Cooking time
less than 10 mins
Serves
Serves 4
A potent combination of fresh mackerel, pungent horseradish and refreshing cucumber that’s a smashing start to any meal.
For the salted cucumber and horseradish, place the cucumber slices into a colander and sprinkle with plenty of salt. Mix well and leave the contents to drain over the sink for half an hour.
Rinse the salt off the cucumber with cold water, then leave to drain. Gently wring out any excess moisture from the cucumber with your hands, then set aside.
In a clean bowl, mix the horseradish with the crème fraîche and mustard powder, making sure the mustard powder is well combined with no lumps. Set aside.
Season the mackerel fillets on their skin side with salt and freshly ground black pepper.
Heat the butter in a frying pan until it is foaming, then add the fillets skin-side down. Place a heat-proof plate onto the cooking fillets, as this will make sure they stay flat and cook evenly. Cook for 4-5 minutes, or until nearly cooked through, then turn the fillets and cook for 30 seconds, or until just cooked through.
To serve, place a small handful of the cucumber onto the toast. Place the cooked mackerel fillets onto the cucumber. Place a dollop of the horseradish sauce on top and garnish with a little of the sliced red onion and a squeeze of lemon.


Server Setup
Human Requirements
Unfortunately, this process is still technical enough that you will need a devops person to at least get the system set up for processing. You’ll also need people who can reorder PDF pages (if necessary) as well as people who can enter and review newspaper issue metadata.
Somebody will want to monitor the output from the various automated processes, such as QCing generated batches on a staging server prior to loading in production, as there is still a great deal of room for human error.
Preliminary setup
Before anything can be done, the following setup has to happen:
- Make sure you understand the Services documentation and can get the stack up and running
- Somebody symlinks or otherwise sets up the sftp folder root so that each
title has its own location directly off said root. e.g.,
/mnt/news/sftp/foo
should contain one title’s issues, and/mnt/news/sftp/bar
should contain a different title’s issues. - Somebody sets up the full swath of folders, mounting to network storage
as it makes sense.
PDF_UPLOAD_PATH
(/mnt/news/sftp
): One subfolder should be set up per titleSCAN_UPLOAD_PATH
(/mnt/news/scans
): This is where in-house scans would be uploaded.ORIGINAL_PDF_BACKUP_PATH
(/mnt/news/backup/originals
): Short-term storage where uploaded PDFs will be moved after being split. They may need to be held a few months for embargoed issues, but they’re auto-purged once the issue has been put into a batch.PDF_PAGE_REVIEW_PATH
(/mnt/news/page-review
): Issues which came from born-digital SFTP uploads and are ready for manual page reordering - this should be exposed to whomever will manually review and reorder the born-digital uploads prior to them entering the rest of the workflow.BATCH_OUTPUT_PATH
(/mnt/news/outgoing
): Batches here are ready for ingest into staging and eventually productionWORKFLOW_PATH
(/mnt/news/workflow
): Issues are moved here for processing, and once here should never be accessible to anybody to manually modify them. They will live here until all workflow tasks are complete and they’re put into a batch for ingest.ISSUE_CACHE_PATH
(/var/local/news/nca/cache
): This just needs to be created. The app will use this to speed up issue lookups.
- Make sure that the workflow path and the batch output path are on the same filesystem! This ensures the batch generator will be able to hard-link files, rather than copying them, which saves a significant amount of time when building large batches. NOTE: the system currently requires this, and will fail if an attempt to hard-link files fails.
- Permissions have to be set up such that:
- Humans can rename PDFs in the page review path
- Humans can drop off scanned PDF/TIFF pairs in the scans path
- Humans can upload born-digital PDFs into the sftp path
- All binaries (
server
,run-jobs
, anything else inbin/
you wish to run) are run as a user who can read and write to all paths - Apache can read the scans path
- The system which ingests batches into ONI can read from the batch output path
- Run the servers and set up one or more users: User Setup
- Somebody must set up the list of newspaper titles using the “Manage Newspaper Titles” functionality. Nothing works if titles aren’t set up! Titles need all data except the username and password, which are primarily there to help keep the information central.
- Somebody has to set up at least one MARC Org Code in the admin app’s “MARC Org Codes” area. This should match the code set up in the app’s settings. If in-house scanning is done, and awardees will differ from your primary awardee’s code, you would set up those awardees before putting their scanned images into the scan folder.


Abi's Portfolio
About Me
My name is Abirami Patchaiyappan, Abi for short. I am currently a sophmore at UC Santa Cruz, studying computer science and cognitive science. I love arts and creativity.
I'm from San Jose and have lived in the Bay Area all my life. Here's a picture of me at Santana Row, San Jose.
My family is from Pondicherry, India. Fun Fact, this is where the main character in the book "Life of Pi" is from. Here's a picture of one of my favorite beaches in Pondicherry.
Hobbies
I enjoy drawing, painting, and many forms of arts and crafts. Here is a gif of an animation I hand drew.
Projects
- SnapJams - a web app which can recognize facial emotion and redirects the user to a playlist based on their mood
- An Audio Reality for the Blind - a program which identified an image based on pixel comparison and relayed an audio out put describing the image


cup.storage package
init for cup.storage
Submodules
cup.storage.obj module
- description
Object related storage
- class cup.storage.obj.AFSObjectSystem(config)[source]
Bases:
ObjectInterface
AFSObjectSystem implemented interface.
- delete(path)[source]
delete a file
- Parameters
path – object path
- Returns
{ 'returncode': 0 for success, others for failure, 'msg': 'if any' }
- get(path, localpath)[source]
get the object into localpath
- Returns
{ 'returncode': 0 for success, others for failure, 'msg': 'if any' }
- head(path)[source]
get the object info
- Returns
{ 'returncode': 0 for success, others for failure, 'msg': 'if any' 'objectinfo': { size: 1024, ....... } }
- mkdir(path)[source]
mkdir dir of a path
- Returns
{ 'returncode': 0 for success, others for failure, 'msg': 'if any' 'objectinfo': { size: 1024, ....... } }
- class cup.storage.obj.FTPObjectSystem(config)[source]
Bases:
ObjectInterface
ftp object system, Plz notice all methods of FTPObjectSystem is NOT thread-safe! Be careful when you use it in a service of concurrency.
- head(path)[source]
get the file info
- Returns
{ 'returncode': 0 for success, others for failure, 'msg': 'if any' 'fileinfo': [ "-rw-rw-r-- 1 work work 201 Nov 9 17:03 __init__.py" ] }
- class cup.storage.obj.LocalObjectSystem(kvconfig=None)[source]
Bases:
ObjectInterface
local object system
- class cup.storage.obj.S3ObjectSystem(config)[source]
Bases:
ObjectInterface
s3 object system
- delete(path)[source]
delete a file
- Parameters
path – object path
- Returns
- {
‘returncode’: 0 for success, others for failure, ‘msg’: ‘if any’
}
- delete_bucket(bucket_name, forcely=False)[source]
delete bucket
- Parameters
forcely –
- if forcely is True, the bucket will be delete no matter it has
objects inside. Otherwise, you have to delete items inside, then delete the bucket
- get(path, localpath)[source]
get the object into localpath
- Returns
- {
‘returncode’: 0 for success, others for failure, ‘msg’: ‘if any’
}
- head(path)[source]
get the object info
- Returns
{ 'returncode': 0 for success, others for failure, 'msg': 'if any' 'objectinfo': { size: 1024, ....... } }
- mkdir(path)[source]
mkdir dir of a path
- Returns
{ 'returncode': 0 for success, others for failure, 'msg': 'if any', 'objectinfo': { size: 1024, .. } }


Blazing Saddles A review by Joe Chamberlain
Starring Cleavon Little; Gene Wilder; Slim Pickens; Harvey Korman & Madeline Kahn
I'm giving this stinker 0 out of 10. Normally, the worst that I would ever rate a movie would be 1 out of 10. But the total waste of time that is Blazing Saddles is, compounded by the fact that this movie is incredibly offensive, helped me come to the big goose egg. I'm not sure what the hell Mel Brooks was thinking when he made this thing, or if he was even thinking at all.  In mine, it's not. Or maybe Mel graduated from the Spike Lee school of filmmaking. Because only the self-righteous Lee uses the N-word more often in his films than Brooks did in this one. At least Lee has the smarts to realize that nobody is going to find that term amusing. Brooks bandies it about like he figures the audience will be rolling in the aisles every time they hear it. Wrong Mel! I would call you a boob Mel, but that insults breasts everywhere.
This idiotic attempt at a comedy centers on the evil Lieutenant Governor's (Harvey Korman) attempts to clear out a town so he can buy up the land cheap and sell it to the railroad. He sends his goons to run the townsfolk out. But the town appeals to the governor (Mel Brooks in one of many uninspired, and unfunny roles) to send them a new sheriff to protect them. The governor pawns the task off to Korman's character Hedley Lamarr. (I can tell you are rolling off your chairs right now just thinking of all the humor in that name.) Lamarr decides to send the town a black sheriff (gasp) in the hopes that the town will be so disgusted at the prospect of a black man living among them that they will all just leave. Hold on, I've got to stop while these gales of laughter pass. It's just too funny. Racism passing as humor -- gosh why didn't anybody ever think of that one before? Oh wait, I think somebody might have -- they are called the KKK.  But I digress. Anyway, the black sheriff rides into town amid a flurry of townsfolk using the N-word. Golly, will the hilarity just never end? He ends up joining forces with a drunk (Gene Wilder), who happens to be the former fastest gun in the West. Together, they save the day from evil.
Not one person in this movie gives a decent performance. Wilder looks like he is recovering from a head injury for most of the movie, and Korman looks embarrassed to be a part of the movie. OK, he really didn't -- but he should have.
I did not laugh once during this whole sorry experience. I admit to starting to snicker on a couple of occasions. Actually, the end started to look as if it was going to have some promise, but alas, it ended up being as crappy as the rest of the movie. I can say with full confidence that Blazing Saddles has no redeeming qualities whatsoever. Mel Brooks would be doing the world a favor if he burned every last copy of this film.
0/10
Visit The Movie Guy http://movieguy.tripod.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


Harry Styles's 2020 tour is coming to London next April
by By Jess PhillipsThe news you’ve been waiting for is here. Harry Styles is officially going on tour next year. The former One Direction star announced the 11-month tour on Instagram. Love on Tour kicks off in Birmingham next April, hitting Sheffield and Dublin before arriving at The O2 in London on April 22 and 23.
Two and a half years on from his debut solo record, the singer will be promoting his upcoming 12-track album ‘Fine Line’. He'll be supported by King Princess in the UK and Ireland, Jenny Lewis in the US and Canada, and Koffee in Mexico.
Talking to Rolling Stone in August, Styles said ‘Fine Line’ is about ‘having sex and feeling sad.’ Tim Walker has shot his album cover, and there’s already speculation about a Glastonbury set. Brace yourselves, H2 is full speed ahead.
Tickets will be available here on November 22 at 10am.
For more info on upcoming 2020 gigs, read about the top ten London gigs in 2020.
Want a reminder of what we thought of Styles’s first album? Have a look at our review.


I like babies very much. Especially their crying screams when they are slightly uncomfortable and disturb people working in a silent building or flying tube. Just to be clear to whom it may concern, I DO NOT LIKE babies in any weird way. For example, babies do not activate the happy center of my brain that is the source of pedophilia, I just like them in all the normal ways that people like babies. They are just so darn cute.
"The happier we get, the less we see."- Ralph Waldo Emerson
Babies are not the only things that bring joy to my life, skating tends to brighten my day when I am having a down day.  They are giant buttholes, like humungous buttholes.   While they are good at skating and possibly even better than me, unbelievable right?, better than me?!, shocking!, they are the definition of each curse word in the English dictionary. Asses, bitches, douches and even *****. Anyways skating is passion, my dream. It is exhilarating to feel the cold wind on my face and feeling every little rock the wheels come in contact with.
Facebook


| corresp {MASS} | R Documentation |
Find the principal canonical correlation and corresponding row- and column-scores from a correspondence analysis of a two-way contingency table.
corresp(x, ...) ## S3 method for class 'matrix' corresp(x, nf = 1, ...) ## S3 method for class 'factor' corresp(x, y, ...) ## S3 method for class 'data.frame' corresp(x, ...) ## S3 method for class 'xtabs' corresp(x, ...) ## S3 method for class 'formula' corresp(formula, data, ...)
x, formula |
The function is generic, accepting various forms of the principal
argument for specifying a two-way frequency table. Currently accepted
forms are matrices, data frames (coerced to frequency tables), objects
of class |
nf |
The number of factors to be computed. Note that although 1 is the most usual, one school of thought takes the first two singular vectors for a sort of biplot. |
y |
a second factor for a cross-classification. |
data |
a data frame against which to preferentially resolve variables in the formula. |
... |
If the principal argument is a formula, a data frame may be specified as well from which variables in the formula are preferentially satisfied. |
See Venables & Ripley (2002). The plot
method produces a graphical
representation of the table if nf=1
, with the areas of circles
representing the numbers of points. If nf
is two or more the
biplot
method is called, which plots the second and third columns of
the matrices A = Dr^(-1/2) U L
and B = Dc^(-1/2) V L
where the
singular value decomposition is U L V
. Thus the x-axis is the
canonical correlation times the row and column scores. Although this
is called a biplot, it does not have any useful inner product
relationship between the row and column scores. Think of this as an
equally-scaled plot with two unrelated sets of labels. The origin is
marked on the plot with a cross. (For other versions of this plot see
the book.)
An list object of class "correspondence"
for which
print
, plot
and biplot
methods are supplied.
The main components are the canonical correlation(s) and the row
and column scores.
Venables, W. N. and Ripley, B. D. (2002) Modern Applied Statistics with S. Fourth edition. Springer.
Gower, J. C. and Hand, D. J. (1996) Biplots. Chapman & Hall.
(ct <- corresp(~ Age + Eth, data = quine)) plot(ct) corresp(caith) biplot(corresp(caith, nf = 2))


Participate as the first airline in insurance network
Airline to submit flight
Passenger to pick a flight
Passenger/Anyone to check flight status
(You will need to fetch available flights ^ before seeing some flight options)
(keep trying to fetch till you get an alert of the response)
Passenger to check their balance
(You will need to fetch flight status before seeing your accurate balance)
Passenger to withdraw their balance


Darn. Your browser does not support 3d transforms, and the 3d stuff here won't work for you. If you want to check it out, try Safari or a dev build of Chrome.
Created by @zachleat.
Back to the blog post.


Researchers explore how citizens can become agents of environmental change
A blueprint for how to educate people to maximize their impact
| Source: | Stanford University |
| Summary: | Some programs work better than others when it comes to involving citizens in preserving the environment. After reviewing those that worked, researchers propose a blueprint for how others can educate people to maximize their impact. |
If you like to walk in the woods, raft a river, dig in a garden or look at butterflies, you could become an agent of change.
Science and policy may not be enough to solve complex environmental challenges ranging from species extinction to water pollution, but actively engaged citizens could tip the balance, according to a new Stanford-led study that provides a blueprint for empowering people to turn the tide of environmental destruction. In Biological Conservation, the researchers outline four key facets of programs that have been successful in motivating and training people to have a meaningful impact.
"Effective environmental education moves people to persistent action through engaging with issues in relevant ways," said study lead author Nicole Ardoin, an associate professor at the Stanford Graduate School of Education and a senior fellow at the Stanford Woods Institute for the Environment. "Without it, making sustained change on environmental and sustainability issues simply is not possible."
While the rate of climate change and species extinction intensifies, the U.S. outdoor recreation sector is growing more than one-and-a-half-times faster than the overall economy. Historic federal legislation passed earlier this year is opening more than a million acres of wildlands to public access. Increasingly, nonprofit groups and government agencies are harnessing this growing interest in nature as a force for conserving it. The question for them has been what kinds of activities or educational engagement have the most measurable impact.
To get at that question, the researchers analyzed reviews of more than 100 environmental education programs that addressed topics such as habitat protection and restoration, water quality, energy conservation, climate change and recycling. From this, the researchers gleaned four keys to maximizing the chance that programs will help citizens make meaningful environmental impacts: focus on locally relevant issues; collaborate with experts; incorporate action-oriented learning strategies and approaches, such as hands-on experiments and policy recommendations; and measure outcomes.
The researchers point to citizen science as an example of the four principles at work. At its best, citizen science involves members of the general public participating in aspects of science initiatives from design to implementation. Their hands-on engagement in the conservation effort yields reliable, usable data. These initiatives provide community members with avenues for collecting and measuring local-scale data, working directly with scientists and research managers on relevant research and documenting outcomes.
Incorporating the study's findings into new environmental education programs could help more conservation organizations and agencies involve the public effectively in improving environmental quality. It could also help cyclists, river rafters, hikers and others contribute directly to the nature they enjoy.
Environmental education: Keys to success
1) Focus on local environmental issues or locally relevant dimensions of global issues
Example: Students in a reforestation project created nurseries, improved their abilities to serve as custodians, and participated in plantings on school grounds, as well as in other deforested parts of the community, with the goal of reconnecting with local ecosystems and enhancing student capabilities to serve as custodians.
2) Collaborate with scientists and resource managers
Example: A program brought together prison inmates with scientists, students and natural area managers to encourage lifelong learning, support ecological research and promote habitat restoration through plant production and captive rearing of animals in correctional facilities. Conservation practitioners provided the knowledge that resulted in raising and releasing approximately 550 frogs, 4,000 butterflies and 1 million plants.
3) Incorporate action elements into programs
Example: University students' sea turtle research and habitat assessment resulted in a proposal to the Mexican government for a marine protected area, with recommendations for fishing activity zones for resource and ecotourism uses.
4) Measure and report program outcomes
Example: Researchers in a reforestation education initiative reported not only the number of trees planted but also provided data on the survival rates of planted trees.
Study co-authors include researchers from Virginia Tech and 4Research. The North American Association for Environmental Education funded the research through its eeWORKS initiative, a collaboration among nonprofit organizations and government agencies.
Ardoin is also director of the Emmett Interdisciplinary Program in Environment and Resources (E-IPER) in the School of Earth, Energy & Environmental Sciences (Stanford Earth).
make a difference: sponsored opportunity
Story Source:
Materials provided by Stanford University. Original written by Rob Jordan.
Note: Content may be edited for style and length.
Cite This Page:
| MLA | Stanford University. "Researchers explore how citizens can become agents of environmental change: A blueprint for how to educate people to maximize their impact." ScienceDaily. ScienceDaily, 14 November 2019. <www.sciencedaily.com/releases/2019/11/191114154458.htm>. |
| APA | Stanford University. (2019, November 14). Researchers explore how citizens can become agents of environmental change: A blueprint for how to educate people to maximize their impact. ScienceDaily. Retrieved November 17, 2019 from www.sciencedaily.com/releases/2019/11/191114154458.htm |
| Chicago | Stanford University. "Researchers explore how citizens can become agents of environmental change: A blueprint for how to educate people to maximize their impact." ScienceDaily. www.sciencedaily.com/releases/2019/11/191114154458.htm (accessed November 17, 2019). |


Kiwi - Web Browser History Visualizer
Dashboard
Overview
Charts
Settings
Overall Time Distribution
Process PNG
Productivity vs. Procrastination
Process PNG
Most Active Days
Process PNG
Most Active Hours
Process PNG


[REVISION 20070302]
- NEW
- Validation may be limited to specific columns by calling schema_validations
from within your model class, passing either a single column (:only =>
:name) or an array of columns (:except => [:isocode, :iddcode]).
- CHANGED
- Use symbols rather than strings when calling validation methods as this
seems to be the "way of the future" :).
[REVISION 20070224]
- FIXED
- Removed useless assignment of class variable.
[REVISION 20070221]
- NEW
- Where possible, validates_uniqueness_of adds the :case_sensitivity option
based on the presence of case-insensitive indexes.
[REVISION 20061203]
- CHANGED
- Lazily load meta-data during allocate/new rather than inherited.
- FIXED
- Explicit table name ignored.
[REVISION 20061202]
- CHANGED
- Use Rails 1.2 alias_method_chain.
- CHANGED
- Separate modules into individual files.
[REVISION 20061114]
- FIXED
- NOT NULL columns with a default not marked as required for update.
[REVISION 20061013]
- NEW
- install.rb informs user of missing dependencies.
[REVISION 20061012]
- CHANGED
- Only read meta-data for base-classes.
[REVISION 20061011]
- CHANGED
- Use include rather than extend in init.rb as this is more general. Plugin
code can then determine if it needs to use extend or not.
[REVISION 20061020]
- FIXED
- Breaks abstract class inheritance. If classes are named
‘AbstractXxx’ they will be treated as abstract. This is
somewhat of a work-around for the current implementation however I believe
it is a sensible choice for now.
[REVISION 20060924]
- FIXED
- validates_uniqueness_of causes new records to fail when nullable column is
null and there exists another record where the value of the column is also
null. NULL values should always be considered unique.
[REVISION 20060915]
- NEW
- Multi-column unique indexes are converted to validates_uniqueness_of with
scope. The column validated for uniqueness is either the last column not
ending in ‘_id’ or simply the last column. This follows the
typical composite unique index column ordering where the scoping is
specified first but will attempt to find the last non-foreign-key column
just-in-case. Eg, both add_index :states, [:country_id, :name], :unique
=> true and add_index :states, [:name, :country_id], :unique => true
would result in <code>validates_uniqueness_of :name, :scope =>
[:country_id].
[REVISION 20060914]
- CHANGED
- Removed unnecessary condition from validates_presence_of for associations.
[REVISION 20060913]
- FIXED
- validates_presence_of for associations causes new records to fail.
[REVISION 20060912]
- FIXED
- ‘Before updating scaffolding from new DB schema, try creating a table
for your model (<model>)’ when running ./script/generate
scaffold <model>. Seems the scaffold sandbox dynamically creates
classes which have no name.
[REVISION 20060911]
- CHANGED
- Revert to nil defaults—as opposed to blank—now that the MySQL
behaviour has been patched in redhillonrails_core.
[REVISION 20060909]
- NEW
- Dependency on RedHill on Rails Core.
- NEW
- validates_uniqueness_of for associations.
- FIXED
- validates_presence_of for associations.
[REVISION 20060908]
- FIXED
- validates_presence_of not being applied under MySQL; empty defaults are
represented as blank rather than nil.
- NEW
- validates_uniqueness_of for associations.
[REVISION 20060818]
- FIXED
- ‘Before updating scaffolding from new DB schema, try creating a table
for your model (<model>)’ when running ./script/generate
scaffold <model>.
- FIXED
- ‘relation "system_settings" does not exist’ when
running a migrate with system_settings plugin installed.
[REVISION 20060816]
- FIXED
- Overly greedy regex ignoring all date/time columns.
[REVISION 20060812]
- CHANGED
- Documentation updated to reflect the fact that no further action is
required once the plugin is installed.
[REVISION 20060812]
- FIXED
- Documentation mentions :integer => true options; this should have read
:only_integer => true.
[REVISION 20060803]
- FIXED
- Revision 50 comments out the validates_presence_of magic on line 13 in
belongs_to_with_schema_validations.
[REVISION 20060802]
- NEW
- Support for validates_uniqueness_of for single-column unique indexes.
- CHANGED
- Error message for boolean fields to be the same as the default for
validates_presence_of
[REVISION 20060723]
- FIXED
- Workaround for a "feature" of the way validates_presence_of
handles boolean fields. See dev.rubyonrails.org/ticket/5090
and dev.rubyonrails.org/ticket/3334
[REVISION 20060719]
- NEW
- Support validates_presence_of for belongs_to associations.
[REVISION 20060718]
- FIXED
- String test checks class instead of klass
- CHANGED
- Separated out check for null from validation of numericality. This means
you’ll get a "xxx can’t be blank" rather than an
"xx isn’t a number" which seems more intuitive to me.
- FIXED
- Default check should consider nil explicitly to allow for false.
[REVISION 20060717]
- NEW
- Initial version.
- FIXED
- Ignore columns ending in: _id, _count, _at, _on.
- NEW
- Support validates_numericality_of for numbers (including :integer =>
true)
- NEW
- Support validates_length_of for strings


this is a paraghraph
in 1 paragraph this is bold ke toosh bold dare
paragraph2 this is strong. ke toosh strong dare
in matne kaje ba em mishe az i estefade kard
in matn ba i hast ke mibini
this is artichle
this is h one
this is h three
this is h two
this is paraghrph
- shanbe
- yek
- do
- masi
- yavari
- bar ax
- as
- test
- Head north on N Halsted St
- Turn right on W Diversey Pkwy
- Turn left on N Orchard St
- study
- The devotion of time and attention to acquiring knowledge on an academic subject, especially by means of books
- design
- A plan or drawing produced to show the look and function or workings of a building, garment, or other object before it is built or made
- Purpose, planning, or intention that exists or is thought to exist behind an action, fact, or material object
- business
- work
- A person's regular occupation, profession, or trade
- Walk the dog
- Fold laundry
-
Go to the grocery and buy:
- Mow the lawn
- Make dinner
w3
Email Me
back to top


Amsterdam JSNation Conference 2019
Kyle Simpson
«You Don't Know JS»
Tobias Koppers
Michele Weststrate
MobX
Matteo Collina
David Mark Clements
Что было:
«With great power comes great responsibility»
Основное:
Не менее основное:
«TypeScript solves the problems I don't really have in the ways I don't really like»
Tom Dale (Ember): Compilers are the New Frameworks
«Every ecosystem makes its own language. I'm not sure that this future is a future we really want to get to»
Krzysztof Kotowicz
Securing the DOM from the bottom up
Gleb Bahmutov
Testing tools and their friends
Tobias Koppers
Webpack 5 - Why Breaking Changes? What is Next?
Michele Weststrate
Immer, Immutability and the Wonderful World of Proxies
TL,DR:
Mat Groves
Turbo Charging 2D on the Web
Paulo Lopes
10 Things I Learned Making the Fastest JS Runtime in the World
Thomas Watson
Postmortem NodeJS debugging
Jasper Schulte
Спасибо!


Home
About
Log in
Sign up
I built the website use HTML and CSS.
I built the website use HTML and CSS.
I built the website use HTML and CSS.
I built the website use HTML and CSS.
I built the website use HTML and CSS.
I built the website use HTML and CSS.
I built the website use HTML and CSS.
I built the website use HTML and CSS.
I built the website use HTML and CSS.


§205A-49 Adoption of rules. Each agency charged with carrying out this part shall adopt rules necessary to implement or comply with this part by July1, 1990. All rules shall be adopted under chapter 91. [L 1986, c 258, pt of §1; am L 1989, c 356, §15]


This is the new Hooting Yard site, which you may have reached by searching for one of the terms in the
duffel-coat homunculus pencil sharpener baize tungsten hebetude ullage toxin orlop custard Ordnance Survey Map guillemot basin creosote bandages orrery airbag gristle linctus subterfuge porlock hobbledehoy mucker crumple scrofula usufruct flap palinode chutes myrmidon bindweed vinculum blazer sponge porridge remorse pelf cyclops treadmill pins Richard Milhous Nixon dubiety whelp sandpaper coathangers tinpot gluten cormorant ectoplasm Heliogabalus fool's paradise dirigible clunk gutta percha fudge recklessness tornado industry goo plinth sandwich paste bewolfenbuddlement cake bile Dobson toffee brilliantine catastrophe poop deck fanfaronade milk tuberculosis owls vermilion Gerard Manley Hopkins pilgarlic shuddering conclave glue haemoglobin windjammer snood Bolshevik plankton theory blister haberdashery concupiscience puddings towel dragonfly Clytemnestra! poltroon grotesque ostrich-shaped mannequin vinegar Donald Rumsfeld chrysanthemums prong stamp collection threnody


Arsenicals, Glutathione Reductase and Cellular Redox Status
EPA Grant Number: R826136Title: Arsenicals, Glutathione Reductase and Cellular Redox Status
Investigators: Stýblo, Miroslav , Beck, Melinda A. , Cullen, William R.
Current Investigators: Stýblo, Miroslav , Beck, Melinda A. , Cullen, William R. , Del Razo, Luz M. , Lin, Shan , Walton, Felecia
Institution: University of North Carolina at Chapel Hill , University of British Columbia
EPA Project Officer: Rosenthal, Sheila
Project Period: September 1, 1997 through August 31, 2000 (Extended to September 14, 2001)
Project Amount: $322,936
RFA: Arsenic Health Effects Research (1997) RFA Text | Recipients Lists
Research Category: Drinking Water , Health Effects , Human Health , Water
Description:
The proposed research will examine two related aspects on the mode of action of inorganic arsenic (iAs) as a carcinogen and toxin including (i) interactions of iAs and its metabolites with glutathione reductase (GR), a key enzyme in redox metabolism of glutathione (GSH), and (ii) effects of the arsenic-GR interactions on ratio of GSH to glutathione disulfide (GSSG) that is an indicator of cellular redox status.
Objectives/Hypothesis:
The following hypothesis will be tested:1. Exposure of cultured human cells or intact mice to arsenicals results in inhibition of GR activity.
2. Trivalent methylated arsenicals and/or arsenothiols are the most potent inhibitors of GR. Hence methylation of iAs yields potentially toxic compounds.
3. A consequence of the inhibition of GR by arsenicals is an alteration of the intracellular GSH/GSSG ratio and of the redox status of cells.
4. Other NAD(P)H-dependent oxidoreductases may be inhibited by the arsenicals and inhibition of these enzyme may also be a means by which arsenic alters the redox status of cells.
Approach:
The proposed research will integrate studies at three levels of biological complexity: Purified enzyme, cultured cells and intact animals. The approaches and goals can be summarized as follows: (i) examination of the interactions of iAs and its metabolites (including pentavalent and trivalent methylated arsenicals and arsenothiols) with GR purified from human erythrocytes; (ii) examination of effects of arsenicals on GR activity, GSH/GSSH ratio and intracellular peroxides in cultured human cells as compared with patterns of arsenic metabolism (uptake and efflux, reduction, methylation and protein binding) in cells; and (iii) examination of the in vivo effects of arsenicals on GR activity and the GSH/GSSG ratio in tissue of mice.
Expected Results:
Given the previously published data, the result of the proposed experiments are expected to show that trivalent methylated arsenicals and arsenothiols are potent inhibitors of GR from human erythrocytes, GR in cultured human cells and mouse tissues. These results will provide novel information about the relation between metabolic conversion of iAs and mechanism of its toxic effects. This finding would suggest that methylation of iAs is not necessarily a detoxification process as it yields potentially toxic trivalent methylated metabolites that may be responsible for some of the adverse effects in exposed organisms. Results of in vivo experiments on mice will provide data about critical levels of exposure to arsenicals that affect activity of GR and the GSH/GSSG ratio in tissues. These data may contribute to the evaluation of the risk of health effects associated with environmental and occupational exposure to arsenicals.
Publications and Presentations:
Publications have been submitted on this project: View all 43 publications for this projectJournal Articles:
Journal Articles have been submitted on this project: View all 12 journal articles for this projectSupplemental Keywords:
drinking water, risk assessment, health effects, human health, animal, mammalian, metals, methylation, reduction, uptake, efflux, detoxification, arsenothiols, mechanism, inhibition, protein binding, cell culture, mouse., RFA, Health, Scientific Discipline, Toxics, Waste, Water, Ecosystem Protection/Environmental Exposure & Risk, POLLUTANTS/TOXICS, National Recommended Water Quality, Arsenic, Fate & Transport, Risk Assessments, Disease & Cumulative Effects, Water Pollutants, Biology, Drinking Water, cancer risk, Pathology, fate and transport, health effects, carcinogenesis, human health effects, cellular metabolism, redox metabolism, arsenothiols, trivalent methylated arsenicals, detoxification, cellular biology, exposure and effects, cell biology, exposure, inorganic arsenic, cellular physiology, effects, carcinogens, human exposure, toxicity, GSH, methylation, metabolism, water quality, protein bindingProgress and Final Reports:
1999 Progress Report2000 Progress Report
Final Report


Auth
@include('./components/features/auth/auth.html')
Preview
@include('./components/features/preview/preview.html')
About
@include('./components/features/about/about.html')
Reviews
@include('./components/features/reviews/reviews.html')
Features
@include('./components/features/features/features.html')
Statistics
@include('./components/features/statistics/statistics.html')
News
@include('./components/features/news/news.html')
Partners
@include('./components/features/partners/partners.html')


Mueller Probe Offers Dems Another Avenue to Impeaching Trump
by MEGAN MINEIROWASHINGTON (CN) — House Democrats confirmed in federal court papers Tuesday that they are formally investigating whether the president lied to former special counsel Robert Mueller.
The disclosure appears in a case where the House Judiciary Committee seeks to compel testimony from Don McGahn, the former White House counsel who emerged as a central character in Mueller’s report on Russian meddling in the 2016 U.S. election.
But House attorney Douglas Letter also highlighted the new arm of the impeachment inquiry a day earlier, at a hearing in the D.C. Circuit.
Citing testimony from a top campaign aide during the trial this fall of Roger Stone, Letter emphasized that Stone was convicted on seven counts of lying to Congress about his communications with President Donald Trump on the 2016 campaign trail regarding upcoming WikiLeaks releases of Russian-hacked documents.
A longtime adviser to the president, Stone joins other convicted Trump insiders to face prison time for crimes uncovered by Mueller’s two-year investigation into Russian interference in the 2016 presidential election. Michael Cohen and Paul Manafort have begun their sentences, while Michael Flynn and Rick Gates await sentencing after pleading guilty.
“They are lying about things that go directly to the Mueller report,” Letter told the D.C. Circuit.
Gates, the 2016 deputy Trump campaign manager, was considered the star witness of Stone’s. He described a call he overheard between Stone and Trump, after which the president told Gates that more releases of stolen WikiLeaks emails, damaging to his Democratic opponent Hillary Clinton, were coming.
Letter wrote Tuesday to the judge presiding over McGahn’s subpoena challenge that Trump gave Mueller a written statement where he denied “any recollection of conversations with Stone about WikiLeaks and any awareness of Stone discussing WikiLeaks with other campaign officials.”
The outcome of the Stone trial underpins the House claim that there is an “even more pressing” need for the court to force McGahn’s testimony, according to Letter’s request for expedited ruling
“Given that the House’s impeachment inquiry is proceeding rapidly, the committee has a finite window of time to effectively obtain and consider McGahn’s testimony,” Letter added.
Prosecutors said Stone lied to Congress because “the truth looked bad for Donald Trump.” House Democrats now aim to bring the accusation to Capitol Hill in the impeachment inquiry centered on reports that Trump illegally pressured Ukraine to investigate his political rival, former vice president Joe Biden.
The committee will hold impeachment hearings after the House Intelligence Committee concludes the public testimonies that kicked off last week in televised proceedings.
Copyright © 2019 courthousenews.com


Hi, I'm Vivek Bhookya.
// VISIT THE DEV LOGS //
I am
I do
I think
Thank you for visiting!
Vivek Bhookya


Register Here
Enter Username
Email
Enter Password
Confirm password
Register
Already having an account?
Login Here!


© 2014 - {{ site.time | date: "%Y" }} {{ site.company.name }} Privacy Policy | Terms of Service Night Sky image courtesy of Scott Wylie under CC by 2.0, some rights reserved.


Reid Burke, Yahoo! Inc.
Upstage lets you create HTML presentations.

My Wonderful Title

Some points:

Point 1

Point 2

Point 3

var deck = new Y.Upstage({
srcNode: "#bd"
});
deck.plug([
Y.Plugin.UpstageKeyboard,
Y.Plugin.UpstageBlank,
Y.Plugin.UpstageGesture,
Y.Plugin.UpstagePermalink
]);
deck.render();
Slides are plain HTML.
Upstage transforms your markup into a presentation, complete with transitions, touch and mouse gestures, and keyboard interaction.
Upstage itself is a tiny (3K) YUI 3 Widget, which relies on Widget plugins to provide its features, so you can use only what you need.
Presenting with HTML is not for everyone. There are some good reasons:
Code is highlighted by Google Code Prettify.
function Conference() {
this.attendees = "you";
}
Conference.prototype.isAwesome = function() {
if (this.attendees.indexOf("me") === -1) {
throw new Error("Without me, it's just Aweso.");
}
return true;
};
var yuiconf = new Conference();
if (yuiconf.isAwesome()) deck.fire("warp", 1);
The Upstage core, upstage-slideshow
, provides the framework for the presentation.
Make it useful by plugging in some of these:
B
to blank the show. Great for Q&A!
Get the Upstage YUIConf 2011 code now!


Glow commando
Loading packages into glow via script tags.
This is provided as a manual test to ensure that pckages load correctly via script tags.
Is glow defined?
Is glow.sidgets defined?


TRUE LIES A film review by John M. Bozeman Copyright 1994 John M. Bozeman
I love a good movie that skillfully unites a variety of genres. Indeed, the "Lethal Weapon" series, in the mind of this reviewer, is a modern classic as a result of its brilliant mixing of thriller, comic, and tragic elements. Achieving such a blend also appears to have been the goal of the makers of TRUE LIES, in which an agent for a super-secret government agency unintentionally finds his family involved as he fights a ring of crazed Muslim terrorists intent on setting off nuclear bombs in the United States.
Our hero, played by none other than Arnold Schwarzenegger, leads a double life. Supposedly, he is a mild-mannered computer salesman. In fact, he is so mild mannered that his wife (Jamie Lee Curtis) is about to have an affair with a used-car salesman posing as a secret agent, simply to give her life more purpose and pizazz. Before long, however, she finds herself involved in real life exploits, as she herself is accidentally vacuumed up along with her husband the terrorists.
TRUE LIES attempts to combine the elements of thriller and domestic comedy. While a number of reviewers have found the movie to be successful in this endeavor, this one is forced to take a much more moderate tone. It is true that there are some genuinely funny moments in the purposely overplayed scenes, as in the case of Arnie's initial encounter with his wife's would-be lover. And some of the chase scenes--such as a motorcycle-and-horse chase through an expensive hotel--are also quite entertaining. But there are also times when the action veers from the merely highly improbable into the simply impossible, such as when a dropped gun manages to kill a sizable number of bad guys while leaving the heros undamaged.
Also, some scenes dragged on too long, and could have used more editing. A couple of these were not only lengthy; they were also embarrassing and gave rise to a sense of moral outrage, as our "hero" uses his access to government facilities not merely to follow, but also to psychologically torture his wife on two occasions.
TRUE LIES is thus a mixed bag. Some aspects of the movie are excellent, but there are also substantial flaws. I would suggest it is good for a matinee or a "bargain" theater, but am less enthusiastic about it as a full price blockbuster.
.
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


Much have been said about the importance of optimizing services that are going to run in a cloud, and they are plenty of resources about the topic, from start up times, memory consumption or resource usage and dozen of data points of your applications.
But even with this amount of information it get exponentially complex to understand why we are doing this?, and what actually means?. So I decided that is going to be simpler to just learn by example, so this is the first part of a series of articles that will help on this matter.
We are going to create a series of services that we will deploy in our kubernetes (k8s) cluster, and we will learn how we could measure them. Them we will optimizing our service to perform better, so we could measure if what we have done improves using data we could use to understand why.
In this first part on the series we will create our base service that will be use as a baseline for comparing the improvements that will be doing down the line, for this our service will be developed with default values, including configuration, forgetting things that we usually do for optimizing an application in order to understand what those optimizations actually do.
We are going to use Spring Initializr https://start.spring.io/ to quickly bootstrap our application.
We will create a Maven Project using Java 8 and Spring Boot version 2.2.2, we will set the Group to be org.learning.by.example.movies, and the Artifact to base-service, the rest of the values should be automatically populated.
For dependencies we will search and add :
Spring Web
Spring Boot Actuator
Spring Data JDBC
PostgreSQL Driver
Now we will click on Generate to download our zip file : base-service.zip, we will uncompress it and leave it ready to be opened with our favorite IDE.
Designing the Service
Before starting to code our application we will design what our application will do, so first lest just look at our movies table loaded in our database, for
this we will do as been doing before using just the PSQL client to explore the data.
Lest explore the data using PSQL, we will login in our server with our moviesuser user so we need to get it password, we could get it with:
We will forward the PostgreSQL port 5432 on our master to our localhost port 6432, this will run until we do ctrl+c :
Finally we can connect to our database with with the provide user and password using PSQL in another
shell :
As we can see we have a in our movies table a column id, as the key of each movie, a column name title that sometimes contains a year and a list of genres, separate with the the character |.
We will do a REST API that returns all the movies from a given genre, but since they are just in a column we need to prepare an special query for it.
We will use the PostgreSQL function string_to_array and the ANY operator for getting all the movies from a given genre, converted to lowercase using the string function lower.
This could return thousands of row, for example for sci-fi will be around 3.5k but that is what we like to do in our service.
Let’s check if with just 10 rows in PSQL
The query seems to work, now lets think on our API, we will create an endpoint in the url /movies/genre that will return all movies under that category as an array of JSON object, but this can not be directly the row in our database it should a bit better, we will design a movie JSON like this :
Implementing our Service
Back to our Service that was generated before we will open it in our favorite IDE and start adding the code require for our service to work.
First we will create a Plain Old Java Object, POJO, class that represents our Movie JSON Object, we will place it in src/main/java/org/learning/by/example/movies/baseservice/model/Movie.java :
This class when deserialize will be just as our designed JSON, now we need we will create our repository that will query database on src/main/java/org/learning/by/example/movies/baseservice/repositories/MoviesRepository.java :
In this simple repository we will extend from CrudRepository to return a Movie List giving a genre, we will use the query that we design before.
But the output of this query does not mach our Movie Classs so we need to create a mapper that will convert a row from our database, we will place on src/main/java/org/learning/by/example/movies/baseservice/mapper/MovieMapper.java :
This simple RowMapper will first use a regular expression to get our movie title and year, if it is available, parse the genres and produce a Movie object, however is not enough to have a mapper we need to tell Spring Data JDBC to use it when query for our Movies so we will set this in a new configuration class on src/main/java/org/learning/by/example/movies/baseservice/repositories/MappingConfiguration.java :
In this MappingConfiguration we are registering our MovieMapper for mapping Movies objects, note that we use dependency constructor injection for obtain the
bean for our MovieMapper.
We will create now a service that will provide movies to who ever request them, to been able to change the implementation of our repository if needed and we will place it on src/main/java/org/learning/by/example/movies/baseservice/service/MovieService.java :
The MovieService class will as well convert to lowercase the genre, since our repository will be perform the query on lowercase genres.
Now we will create our api using a RestController and we will place it on src/main/java/org/learning/by/example/movies/baseservice/controller/MoviesController.java :
Our MovieController will answer HTTP GET request on /movies/{genre} and return the movies using the MoviesService that will use our MoviesRepository, however we need to stablish the connection to our database but first let thinks how this will run on our k8s cluster.
When the service is running we need to connect to our database we could use the environment variables provide by kubernetes to connect to find the IP address and port, as we did in the last example, this are MOVIES_DB_CLUSTER_SERVICE_HOST and MOVIES_DB_CLUSTER_SERVICE_PORT_POSTGRESQL, but we need as well the credentials that we could inject in our kubernetes deployment, as we did before, in a directory containing a username and password. Finally we need to tell spring witch database driver to use, and the JDBC connection string, for this let’s add to our src/main/resources/application.yml some entries :
Let’s get those values using a ConfigurationProperties that will be on src/main/java/org/learning/by/example/movies/baseservice/datasource/DataSourceProperties.java :
Now that we have our DataSourceProperties we could create a DataSource for our connection on src/main/java/org/learning/by/example/movies/baseservice/datasource/MoviesDataSource.java :
We are creating a DriverManagerDataSource with the settings in our application.yml and reading the username and password from our credentials directory.
Finally we will modify our application on src/main/java/org/learning/by/example/movies/baseservice/BaseServiceApplication.java :
We just enable JDBC repositories in our application.
Note: For make this article brief we haven’t include the unit and integrations tests created for this code, but they are available on the repository for this article.
Running our Service in Local
Before start working on deploying the service into our k8s cluster we will run it locally, but since our configuration use a couple of environments variables and some credentials files for this.
First let’s get our user password with :
Now will we save it to a file named /etc/movies-db/password, we will create as well a file name /etc/movies-db/username that just contains our user : moviesuser.
We will build our microservice with :
We will forward the PostgreSQL port 5432 on our master to our localhost port 6432, this will run until we do ctrl+c :
In a new shell window we could run out service, this will run until we do ctrl+c :
Now we could test our service using any HTPP client, such wget, curl, etc., I going to use HTTPie instead :
This will output thousands of records, these where just some of them.
But since we have as well include Spring Actuator in our dependencies we have two more URLs in our service :
Building our Docker Image
Now that we have test that our application runs correctly let’s create a docker image and push it to our local repository that we have in our cluster, first we will create a Dockerfile :
Now we will create a small script that build our docker and publish it to the registry, we will name it build.sh :
Running this script we will build our docker image and push to our local docker registry, but for deploying the image into our cluster we will create a deployment descriptor name deployment.yml :
In this descriptor we are first deploying our service, we declare our liveness and readiness probes to use our actuator endpoint, we inject our credentials and we mount a temporary directory for our service to use. Them we create a k8s service with a load balancer to been able to call our service and balance between the pods that is available.
Finally we will create another script to deploy our service deploy.sh :
This script is a bit different we have create in other tu use the standard kubectl or microk8.kubectl if its available, it will delete the deployment and them deploy our service.
We can now build and deploy our service with :
Now we could check what we have in our cluster for our service with :
Now let’s unzip it and set in path that we could use :
With this now we have available jmeter to be use, however if you are using are high dpi screen, such a 4k or a retina display the JMeter UI may be to small to read but you could edit the file /opt/jmeter/default/bin/user.properties and add this:
Now we could execute jmeter, it will open we a empty test plan, lest just on Name : k8s service load test
We will add a new thread group, right click on the tree panel on k8s service load test and select : Add > Thread (Users) -> Thread Group. Them we will set Number of Threads (Users) = ${__P(NUM_USERS)}, Ramp-up period (seconds) = ${__P(RAMP_UP)}, Loop Count = Infinite, Specify Thread lifetime = Checked, Duration (Seconds) = ${__P(DURATION)}.
No we need to add a HTTP request, right click on the tree pane on Thread Group : Add > Sampler > HTTP Request. Them we will set Name = ${__P(TEST_URL)}, Server Name or IP = ${__P(SERVICE_CLUSTER_IP)}, Port Number = ${__P(SERVICE_PORT)}, Method = Get, Path = ${__P(TEST_URL)}.
Now we will save our plan on k8s-sv-load-test/load_test.jmx.
For launching our load test we wil create a new script on k8s-sv-load-test/k8s-sv-load-test.sh :
This is a very generic script that allow to test any k8s that we have in our cluster, for example if we like to launch a load test against our movies service in the actuator/info endpoint during 30s that will ramp up in 1s :
When the test is complet we get a nice report in html, in this example was on file:////home/jamedina/Sources/movies-base-service/k8s-sv-load-test/report/index.html
But this is a generic script so lets create a more specific to test our movies/genre endpoint on load-test.sh :
Now that we have our script ready we could launch it with
And this is the report that we get
Getting data from Grafana
Now that we have done a simple test we could go to Grafana and look at the graph for this small test
We could see in this test that initial we have a small increase of CPU and them a peak, this was quite rapidly because our ramp up period was just one second,
them we see a dropdown after our test.
In terms of memory we see how slightly increase and remain unmodified during the test.
Scaling
For the next test we will need to increase and decrease the replicas of our service, we will use an small script for this mater name scale.sh
This script will tell K8s to scale our replica to a number and wait until we have the number of replicas that we ask for.
First let’s scale our application to 0 replicas.
Not let’s scale our service to 5 replicas.
And now we will repeat our test but with 10 concurrent users :
And this is the report that we got :
We like to get now the data from Grafana but we will create a copy of the Pods dashboard and name “movies” then we will edit the template to get our al movies pods :
Finally we will get from Grafana the graph for our 5 pods 10 users test :
Getting our measure
Now that we have this tools ready we will defined how we are going to measure this base service, and hopefuly futher services on the nexst parts for the series. We know that we have dozen of different metrics to get from our tools but we are going some very simple with just few data points, and we are not focus on a particular runtime, so they will be not JVM metrics, because we will not haven in all the parts of this series.
We will do this procedure with 1, 10, 25 and 50 concurrent users and 1 replica :
Scale the replicas to 0
Stop our cluster
Start our cluster
Scale to desired number replicas
Run the test for the desire set of concurrent users during 10 minutes with a ramp up of 1 minute
If all request are OK (HTTP response code is 200) :
Get from the JMeter report :
Average response time
Transactions per second
Get from Grafana
Max CPU Usage
Max Memory Usage
If some request are not OK (HTTP response code is not 200)
We will increase the desire number of replicas to one more
Then we will repeat this procedure until we got the results for 100 concurrent users.
We will scale down our replicas and restart our cluster to guarantee that each test is a fresh run, including the database load and connections.
The Results
This are the results for this first example in the series, if you repeat the steps you may get different numbers because they depend on the cluster and the computer that is launching the tests.
C. Users
Pods
ART
TPS
Max CPU
Max MEM
1
1
39.16
25.49
403
474
10
1
570.47
16.73
916
487
25
3
1615.82
14.72
1049
1454
50
5
3190.98
14.89
1351
2499
Java 8 - Spring Boot 2.0 - Spring Web - Spring Data JDBC default settings, unoptimized
With this will close this first article, next we will try to optimize this first service and compare the results with the base.
Note: The full code of this service is available at this repository.