Wednesday, January 30, 2019

Advanced Data Structure — UnionFind. - Find the big brother.


So you decided to take it one step further, huh? Instead of settling with Array and maybe LinkedList.
Although there’s nothing wrong just knowing the basic ones, you still can be a solid developer.
But if you ever want to be a engineer, let’s dive in:

Step 0. Why? (Skip to Step 1 if you are a professional)
What exactly is UnionFind and why do we need it?
Remember Audible and Amazon, eh?
Now who’s the boss?
Yes! Audible belongs to Amazon.
Ok this sounds far too simple, we can just get a HashMap, and just point the Audible to its parent.
Well well well, imagine you are in a system design and need to point thousands of employees to their parent, hmm?
Oh and make it more challenging let’s say the companies are merging and selling all the time.
Great! You agreed we need something efficient and professional.

Step 1. How?
So for professionals I am telling you outright that UnionFind actually is tree.
You were right, using a HashMap or Array would do the job but we need a little delicate path compression and trust me this data structure is full of traps that you can make it full of bugs easily if careless, or even just tired.
For the sake of brevity we are using a simple primitive Java array. (You can swap it with a HashMap easily).
  • 1.1. Constructor
We are simply pointing everybody to himself. Meaning everyone is a disconnected dot. Audible belongs to Audible meaning it is not yet acquired by any other company.
public ConnectingGraph_589(int n) {
    // do intialization if necessary
    father = new int[n + 1];
    for (int i = 1; i <= n; i++) {
        father[i] = i;
    }
}
  • 1.2. Connect
Connect two companies together. e.g. pointing Audible as the son of Amazon. Meaning Amazon acquires Audible.
public void connect(int a, int b) {
    // write your code here
    int rootA = find(a);
    int rootB = find(b);
    if (rootA != rootB) {
        father[rootA] = rootB;
    }
}
  • 1.3. Query
Check if the two companies belong to the same corporation.
This means returning true if Audible and Amazon has the same BIG brother — Amazon.
Or let’s say returning true if Nokia and Microsoft has the same BIG brother — the MS.
public boolean query(int a, int b) {
    // write your code here
    return find(a) == find(b);
}
  • 1.4 Find
This is the best part of the data structure in that you recursively find the BIG brother and update every children in the meanwhile.
private int find(int x) {
    if (father[x] == x) {
        return x;
    } else {
        return father[x] = find(father[x]);
    }
}

Last Step, show me the code:
public class ConnectingGraph_589 {
    private int[] father;

    /*
     * @param n: An integer
     */
    public ConnectingGraph_589(int n) {
        // do intialization if necessary
        father = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            father[i] = i;
        }
    }

    /*
     * @param a: An integer
     * @param b: An integer
     * @return: nothing
     */
    public void connect(int a, int b) {
        // write your code here
        int rootA = find(a);
        int rootB = find(b);
        if (rootA != rootB) {
            father[rootA] = rootB;
        }
    }

    /*
     * @param a: An integer
     * @param b: An integer
     * @return: A boolean
     */
    public boolean query(int a, int b) {
        // write your code here
        return find(a) == find(b);
    }

    private int find(int x) {
        if (father[x] == x) {
            return x;
        } else {
            return father[x] = find(father[x]);
        }
    }
}
For more algorithms feel free to check out my Github https://github.com/oliverwreath/JiuZhang.git

Saturday, January 26, 2019

Ch4 BFS - Bootstrap your algorithms.

Now as it is known to all, the BFS can be easily implemented with the help of a Queue, or more so a FIFO data structure.

But much less known to all, the BFS has quite a few variations of implementation.
For starters, there's two Queue implementation and there's one Queue.
You can use a level counter, or you can simply use a dummyNode.

Alright so here's just one way of going about doing it.

PS: If you are using Java 8 and love succinct code, just use offer and poll methods as they don't invoke type conversion like the addFirst, addLast do. Which can look quite unappreciated.



Ch5 DFS - Bootstrap your algorithms.

As we all know BFS and DFS are the famous two pillars of the Searching algorithms.

Now as we all know BFS can be easily accomplished with a simple Queue. Or let's say a FIFO data structure.

But the DFS remains a tricky one, for we actually usually keep the main function concise and just call a beefy helper function to get it done.

Of course somebody will raise their hand and say "Why not just use recursion?"
Baby, recursion and iterations are not algorithms themselves, however they remains two different styles of implementing the same algorithms.

Now talk is cheap, show me the code:


Tuesday, January 22, 2019

Spring Boot Environment Switch Made Easy

Spring Boot Environment Switch Made Easy

Tired of changing the *.properties file spring.profiles.active=dev to prod every single time before deployment? 
You are NOT alone! 
It is OK to stand up and say, enough! 
application-dev.properties

Step 3 — Setup the Production environment to automatically call PROD profile.

spring.profiles.active=prod
That’s right baby! I go through a bunch of documents and StackOverFlow posts just to find out we only need one simply setting. 
PS: Depending on your AWS Beanstalk environment version, the old posts suggesting SPRING_PROFILES_ACTIVE(Linux environment style) didn’t work. The reason being Amazon aws apparently prefer this style and change them overnight. Yay thanks to me now you probably just dodge a bullet of half and hour. 

Step 2 — Setup the Development environment to automatically call DEV profile. 

The key is to set the JVM options: -Dspring.profiles.active=dev
-Dspring.profiles.active=dev
PS: there could be a pitfall depending on your IDE, as I was caught off-guard seeing all the tests failed! But it turns out that I need to set the JVM options for every single one of the tests too! 
-Dspring.profiles.active=dev

Step 1 — Setup a couple of properties file for each and every environment.

  • Keep your common settings, just leave them right where they are. 
  • Migrate dev settings (e.g.Turn on hibernate sql print; Turn off the view engine cache to see instant change as you write your code) to the application-dev.properties. 
  • Migrate prod settings (e.g. Turn on all sort of caches. Jack up the number of connections in pool.) to the application-prod.properties.

Alright, now you are all set. 
Feel free to comment below share your thoughts experience.
For more technical articles feel free to follow.



Sunday, May 13, 2018

Introduction to Kaggle Machine Learning - Titanic Competition

Have you wonder how the fancy Machine Learning engineers complete their analysis and model training?

How they pick a good model and deploy all those predictions?

Well you are in the right place.

The big picture:

a simple pipeline begins with data massage.

then you will pick an algorithm and train on the data.

deploy your model online and support your business decisions.



So long story short, let's dive in:

1. First of all the Titanic dataset have a bunch of missing data.

so we filled it with NAN or Age.median.

If that a numerical column like the age, fill with median.
If that's a categorical column you can fill in female, or even UNKNOWN.

def fill_NAN(data):
    data_copy = data.copy(deep=True)
    #0, median, max, mean
    data_copy.loc[:, 'Age'] = data_copy.Age.fillna(data_copy.Age.median())
    data_copy.loc[:, 'Fare'] = data_copy.Fare.fillna(data_copy.Fare.median())
    data_copy.loc[:, 'Pclass'] = data_copy.Pclass.fillna(data_copy.Pclass.median())
    data_copy.loc[:, 'Sex'] = data_copy.Sex.fillna('female')
    data_copy.loc[:, 'Embarked'] = data_copy.Embarked.fillna('S')
    return data_copy
 
data_no_nan = fill_NAN(train)
data_no_nan

2. Then since we are using KNN today,

it would be great to change the male to 0, the female to 1. For the sake of the algorithm requirement.

def transfer_sex(data):
    data_copy = data.copy(deep=True)
    data_copy.loc[data_copy.Sex == 'female', 'Sex'] = 0
    data_copy.loc[data_copy.Sex == 'male', 'Sex'] = 1
    return data_copy
 
data_after_sex = transfer_sex(data_no_nan)
data_after_sex


def transfer_embarked(data):
    data_copy = data.copy(deep=True)
    data_copy.loc[data_copy.Embarked == 'S', 'Embarked'] = 0
    data_copy.loc[data_copy.Embarked == 'Q', 'Embarked'] = 1
    data_copy.loc[data_copy.Embarked == 'C', 'Embarked'] = 2
    return data_copy
 
data_after_embarked = transfer_embarked(data_after_sex)
data_after_embarked

3. remove the names since they contribute nothing to the probability. And also remove the cabin since the PClass is a better metric.
# Remove Ticket, Cabin
# type(data_after_embarked)
# np_array = data_after_embarked.values
# type(np_array)
data_after_dropped = data_after_embarked.drop('Ticket', 1)
print(data_after_dropped.shape)
data_after_dropped = data_after_dropped.drop('Cabin', 1)
print(data_after_dropped.shape)
data_after_dropped = data_after_dropped.drop('Name', 1)
print(data_after_dropped.shape)
data_after_dropped

4. Now you can simple run KNN
from sklearn.neighbors import KNeighborsClassifier
def KNN(train_X, train_y, test_X):
    k = 3
    knn = KNeighborsClassifier(n_neighbors = k)
    knn.fit(train_X, train_y)
    pred_y = knn.predict(test_X)
    return pred_y

pred_y = KNN(train_X, train_y, test_X)

print(train.shape)
# train_X = train[:, :]
# train_y = train[:, :]
print(train_X.shape,
     train_y.shape,
     test_X.shape,
      test_y.shape,
     pred_y.shape)

from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
print(accuracy_score(test_y, pred_y))
print(confusion_matrix(test_y, pred_y))
print(classification_report(test_y, pred_y))

5. Or instead I recommend using a 5-fold cross validation:
from sklearn.model_selection import cross_val_score
for k in range(1, 6):
    knn = KNeighborsClassifier(n_neighbors = k)
    print(k, cross_val_score(knn, train_X, train_y, cv= 5))

1 [ 0.65921788  0.68715084  0.7247191   0.69662921  0.66666667]
2 [ 0.66480447  0.69273743  0.71910112  0.69662921  0.68361582]
3 [ 0.65921788  0.7150838   0.7247191   0.74157303  0.72316384]
4 [ 0.67039106  0.70391061  0.69101124  0.70786517  0.70056497]
5 [ 0.65921788  0.67597765  0.69662921  0.7247191   0.72316384]


form which we can see that the k = 3 is the best parameter.

6. Finally adopt the best parameter from your previous experiments, then generate result and submit.

Ok so here are some tricks to speed you up/ avoid some pitfalls:
1. leave id alone, then combine the training and testing data together. So you don't need to apply the same data massage twice.

2. pick the id up at last and put it in the first column of final result.


To sum up,
A. PreProcess:
1. read data
2. Visualization: Heatmap of Correlation
0. Combine for a single pass massaging
1. Feature Selection - drop irrelevant
2. fill NaN
3. white hot encoding
Feature Engineering
Visualization - 'Pearson Correlation of Features'
4. Split back into training and testing
optional 5. chop as you see fit

optional: matplotlib
optional: feature engineering
optional:dropna - X_train=X_train.dropna(axis=1, how='all')

B:
1. cross validation, grid search
1. Generating our Base First-Level Models
2. Second-Level Predictions from the First-level Output

C:
1. final prediction and submit



Friday, April 13, 2018

LintCode 970. Big Business - Weekly13

Big Business, lol

O(n) loop and execute a trade if and only if you can afford it, and also you can gain profit from it.

For any profitable but not yet affordable Business, put them in a minimum Heap.

Finally, check the heap for anything that you can afford and execute anything that's possible.

At last, you can no longer possibly afford anything else, thus return the latest K right away.



LintCode 972. Deliver The Message - Weekly13

http://www.lintcode.com/en/problem/deliver-the-message/


Given the information of a company's personnel. The time spent by the ith person passing the message is t[i] and the list of subordinates is list[i]. When someone receives a message, he will immediately pass it on to all his subordinates. Person numbered 0 is the CEO. Now that the CEO has posted a message, find how much time it takes for everyone in the company to receive the message?
 Notice
  • The number of employees is nn <= 1000.
  • Everyone can have multiple subordinates but only one superior.
  • Time t[i] <= 10000
  • -1 represent no subordinates.

Use a queue to mark this level, and do a BFS search.
Keep updating the shortest time for each employee.
Stop the search whenever everybody's covered.

Then O(n) loop for each employees to get the maximum time and return.