Exemplo n.º 1
0
    def segment(self):

        flattened = flatten_image_matrix(self.image_matrix)  # n X 1

        def component_joint_prob(i):
            a = 0.5 * np.log(2 * np.pi * self.variances[i])
            b = (np.square(flattened - self.means[i])) / (2 *
                                                          self.variances[i])
            c = np.log(self.mixing_coefficients[i])
            return -a - b + c

        z = np.array([
            component_joint_prob(i) for i in range(self.num_components)
        ])  # 3 X n
        gamma_nk_denom = logsumexp(z, axis=0)
        gamma_component = []
        for k in range(self.num_components):
            gamma_nk_nomin = z[k]
            gamma_nk = np.exp(gamma_nk_nomin - gamma_nk_denom)
            gamma_component.append(gamma_nk)
        idx = np.argmax(np.array(gamma_component), axis=0)
        #print(idx)
        image_matrix = np.array([self.means[i] for i in idx.flatten()])
        update_image_values = unflatten_image_matrix(
            image_matrix, self.image_matrix.shape[1])
        return update_image_values
Exemplo n.º 2
0
    def likelihood(self):
        """Assign a log
        likelihood to the trained
        model based on the following
        formula for posterior probability:
        ln(Pr(X | mixing, mean, stdev)) = sum((n=1 to N), ln(sum((k=1 to K),
                                          mixing_k * N(x_n | mean_k,stdev_k))))

        returns:
        log_likelihood = float [0,1]
        """
        flattened = flatten_image_matrix(self.image_matrix)  # n X 1

        def component_joint_prob(i):
            a = 0.5 * np.log(2 * np.pi * self.variances[i])
            b = ((flattened - self.means[i])**2) / (2 * self.variances[i])
            c = np.log(self.mixing_coefficients[i])
            return -a - b + c

        z = np.array([
            component_joint_prob(i) for i in range(self.num_components)
        ])  # 3 X n
        likelihood = logsumexp(z, axis=0).sum()
        return likelihood
        raise NotImplementedError()
    def initialize_training(self):
        """
        Initialize the training
        process by setting each
        component mean to a random
        pixel's value (without replacement),
        each component variance to 1, and
        each component mixing coefficient
        to a uniform value 
        (e.g. 4 components -> [0.25,0.25,0.25,0.25]).
        
        NOTE: this should be called before 
        train_model() in order for tests
        to execute correctly.
        """
        # TODO: finish this

        self.variances = np.array(self.num_components * [1])
        self.flat_values = np.array(flatten_image_matrix(self.image_matrix))
        self.flat_values.shape = (len(self.flat_values), )
        ##set the mean to a random val in the data set
        initial_means_index = np.array(
            sample(range(len(self.flat_values)), self.num_components))
        self.means = np.array(self.flat_values[initial_means_index])
        self.mixing_coefficients = np.array(self.num_components *
                                            [1 / float(self.num_components)])
        self.mixing_coefficients = np.log(self.mixing_coefficients)
    def __init__(self, image_matrix, num_components, means=None):
        """
        Initialize a Gaussian mixture model.
        
        params:
        image_matrix = (grayscale) numpy.nparray[numpy.nparray[float]]
        num_components = int
        """

        self.image_matrix = image_matrix
        self.num_components = num_components
        self.flat_values = np.array(flatten_image_matrix(self.image_matrix))
        self.flat_values.shape = (len(self.flat_values), )
        if (means is None):
            self.means = [0] * num_components
        else:
            self.means = means
        self.means = np.array(self.means)
        self.variances = [0] * num_components
        self.mixing_coefficients = [0] * num_components

        if (len(self.image_matrix.shape) == 3):
            self.height, self.width, self.depth = self.image_matrix.shape

        else:
            self.height, self.width = self.image_matrix.shape
            self.depth = 1
    def test_gmm_best_segment(self):
        """
        Calculate the best segment
        generated by the GMM and
        compare the subsequent likelihood
        of a reference segmentation.
        Note: this test will take a while
        to run.

        returns:
        best_seg = np.ndarray[np.ndarray[float]]
        """

        image_file = 'images/party_spock.png'
        image_matrix = image_to_matrix(image_file)
        image_matrix_flat = flatten_image_matrix(image_matrix)
        num_components = 3
        gmm = GaussianMixtureModel(image_matrix, num_components)
        gmm.initialize_training()
        iters = 10
        # generate best segment from 10 iterations
        # and extract its likelihood
        best_seg = gmm.best_segment(iters)
        matrix_to_image(best_seg, 'images/best_segment_spock.png')
        best_likelihood = gmm.likelihood()

        # extract likelihood from reference image
        ref_image_file = 'images/party_spock%d_baseline.png' % num_components
        ref_image = image_to_matrix(ref_image_file, grays=True)
        gmm_ref = GaussianMixtureModel(ref_image, num_components)
        ref_vals = ref_image.flatten()
        ref_means = list(set(ref_vals))
        ref_variances = np.zeros(num_components)
        ref_mixing = np.zeros(num_components)
        for i in range(num_components):
            relevant_vals = ref_vals[ref_vals == ref_means[i]]
            ref_mixing[i] = float(len(relevant_vals)) / float(len(ref_vals))
            ref_mask = ref_vals == ref_means[i]
            ref_variances[i] = np.mean(
                (image_matrix_flat[ref_mask] - ref_means[i])**2)
        gmm_ref.means = ref_means
        gmm_ref.variances = ref_variances
        gmm_ref.mixing_coefficients = ref_mixing
        ref_likelihood = gmm_ref.likelihood()

        # compare best likelihood and reference likelihood
        likelihood_diff = best_likelihood - ref_likelihood
        print "Reference"
        print gmm_ref.means
        print gmm_ref.variances
        print gmm_ref.mixing_coefficients
        print best_likelihood
        print ref_likelihood
        print likelihood_diff
        likelihood_thresh = 8e4
        self.assertTrue(likelihood_diff >= likelihood_thresh,
                        msg=("Image segmentation failed to improve baseline "
                             "by at least %.2f" % likelihood_thresh))
def k_means_cluster(image_values, k=3, initial_means=None):
    """
    Separate the provided RGB values into
    k separate clusters using the k-means algorithm,
    then return an updated version of the image
    with the original values replaced with
    the corresponding cluster values.

    params:
    image_values = numpy.ndarray[numpy.ndarray[numpy.ndarray[float]]]
    k = int
    initial_means = numpy.ndarray[numpy.ndarray[float]] or None

    returns:
    updated_image_values = numpy.ndarray[numpy.ndarray[numpy.ndarray[float]]]
    """
    # TODO: finish this function
    if (len(image_values.shape) == 3):
        height, width, depth = image_values.shape
    else:
        height, width = image_values.shape
        depth = 1
    flat_values = flatten_image_matrix(image_values)
    #if flat_values.shape[1]==1:
    #   flat_values.shape=(len(flat_values,),)

    if initial_means == None:
        initial_means_index = np.array(sample(range(len(flat_values)), k))
        means = np.array(flat_values[initial_means_index])
    else:
        means = np.array(initial_means)

    diff_max = 10
    count = 0

    while count < 100:  ###insert while condition here for testing whether the clustering has converged
        dist = []
        for i in range(k):
            dist.append(np.sqrt(((flat_values - means[i])**2).sum(axis=1)))

        dist = np.array(dist)
        cluster_indices = dist.T.argmin(axis=1)
        new_means = []
        diff = []
        for i in range(k):
            new_means.append(flat_values[cluster_indices == i].mean(axis=0))
            diff.append(np.sqrt(((new_means[i] - means[i])**2).sum(axis=0)))
        diff_max = max(diff)
        if diff_max < .01:
            count += 1
        means = new_means[:]

    for i in range(k):
        flat_values[cluster_indices == i] = flat_values[cluster_indices ==
                                                        i].mean(axis=0).T
    new_values = unflatten_image_matrix(flat_values, width)

    return new_values
Exemplo n.º 7
0
def k_means_cluster(image_values, k=3, initial_means=None):
    """
    Separate the provided RGB values into
    k separate clusters using the k-means algorithm,
    then return an updated version of the image
    with the original values replaced with
    the corresponding cluster values.

    params:
    image_values = numpy.ndarray[numpy.ndarray[numpy.ndarray[float]]]
    k = int
    initial_means = numpy.ndarray[numpy.ndarray[float]] or None

    returns:
    updated_image_values = numpy.ndarray[numpy.ndarray[numpy.ndarray[float]]]
    """
    # TODO: finish this function
    original_dim = image_values.shape
    flatten_image = flatten_image_matrix(image_values)
    dim = flatten_image.shape
    indicator_indices = np.zeros((dim[0], 1))
    distance = np.zeros((dim[0], k))
    if initial_means == None:
        means_indices = np.random.choice(dim[0], k, replace=False)
        means = flatten_image[means_indices, :].copy()
    else:
        means = initial_means
    previous_means = np.zeros(means.shape)
    while not np.array_equal(means, previous_means):
        indicator = np.zeros((dim[0], k))
        previous_means = means.copy()
        for i in range(k):
            distance[:, i] = np.sum(np.power(
                np.subtract(flatten_image, means[i, :]), 2),
                                    axis=1,
                                    dtype=float)
        indicator_indices = np.argmin(distance, axis=1)
        indx = np.arange(dim[0]).reshape(-1, 1)
        indicator_indices = indicator_indices.reshape(-1, 1)
        indicator[indx, indicator_indices] = 1
        for i in range(k):
            means[i, :] = np.divide(
                np.sum(np.multiply(indicator[:, i].reshape(-1, 1),
                                   flatten_image),
                       axis=0,
                       dtype=float), np.sum(indicator[:, i], dtype=float))

    for i in range(k):
        indices = np.where(indicator[:, i] == 1)
        flatten_image[indices, :] = means[i, :]
    updated_image_values = unflatten_image_matrix(flatten_image,
                                                  original_dim[1])
    return updated_image_values
Exemplo n.º 8
0
def k_means_cluster(image_values, k=3, initial_means=None):
    """
    Separate the provided RGB values into
    k separate clusters using the k-means algorithm,
    then return an updated version of the image
    with the original values replaced with
    the corresponding cluster values.

    params:
    image_values = numpy.ndarray[numpy.ndarray[numpy.ndarray[float]]]
    k = int
    initial_means = numpy.ndarray[numpy.ndarray[float]] or None

    returns:
    updated_image_values = numpy.ndarray[numpy.ndarray[numpy.ndarray[float]]]
    """
    #    raise NotImplementedError()

    #1. If initial is None, create a random initial point list from data
    dim = [
        np.size(image_values, 0),
        np.size(image_values, 1),
        np.size(image_values, 2)
    ]
    if initial_means == None:
        initial_means = getInitialMeans(image_values, k, dim)

    #2. Loop through initial list and subtract it from the data points
    sz = 1
    for i in range(len(dim) - 1):
        sz = sz * dim[i]
    arr_reshaped = flatten_image_matrix(
        image_values)  #np.reshape(image_values,(sz,dim[len(dim)-1]))

    #3. Square sum and root results to get distance from eack k point
    kArray = getDistances(arr_reshaped, initial_means, k)

    #4. Build array containing dataset for each k
    kImage, kIndexes, kMeans = getMeans(arr_reshaped, kArray, k)
    #5. Test for convergence and compile new image data to return
    while (getConvergence(kMeans, initial_means) == False):
        initial_means = kMeans
        kArray = getDistances(arr_reshaped, initial_means, k)
        kImage, kIndexes, kMeans = getMeans(arr_reshaped, kArray, k)

    arr_orig = np.ndarray(shape=(sz, dim[len(dim) - 1]))
    for i in range(k):
        arr_orig[kIndexes[i]] = kMeans[i]

    arr_orig = unflatten_image_matrix(arr_orig, dim[0])
    return arr_orig
Exemplo n.º 9
0
def k_means_cluster(image_values, k=3, initial_means=None):

    import random

    if image_values.ndim == 3:
        row, col, depth = image_values.shape
    else:
        row, col = image_values.shape
        depth = 1

    if initial_means == None:
        initial_means = np.zeros((k, depth))
        random_rows = random.sample(range(row), k)
        random_cols = random.sample(range(col), k)
        for count in range(k):
            initial_means[count] = image_values[random_rows[count]][
                random_cols[count]]

    distance = np.zeros((k, row * col))
    image_values_flat = flatten_image_matrix(image_values)
    means = initial_means
    prev_cluster_allocation = np.zeros((1, row * col))

    while (1):
        for cluster_number in range(k):
            distance[cluster_number] = np.linalg.norm(image_values_flat -
                                                      means[cluster_number],
                                                      axis=1)

        cluster_allocation = np.argmin(distance, axis=0)
        if (np.array_equal(prev_cluster_allocation, cluster_allocation)):
            break

        else:
            prev_cluster_allocation = cluster_allocation

        for cluster_number in range(k):
            indices = np.where(cluster_allocation == cluster_number)
            means[cluster_number] = np.mean(image_values_flat[[indices]][0],
                                            axis=0)

    for cluster_number in range(k):
        indices = np.where(cluster_allocation == cluster_number)
        image_values_flat[[indices]] = means[cluster_number]

    updated_image_values = unflatten_image_matrix(image_values_flat, col)
    return updated_image_values
Exemplo n.º 10
0
def k_means_cluster(image_values, k=3, initial_means=None):
    """
    Separate the provided RGB values into
    k separate clusters using the k-means algorithm,
    then return an updated version of the image
    with the original values replaced with
    the corresponding cluster values.

    params:
    image_values = numpy.ndarray[numpy.ndarray[numpy.ndarray[float]]]
    k = int
    initial_means = numpy.ndarray[numpy.ndarray[float]] or None

    returns:
    updated_image_values = numpy.ndarray[numpy.ndarray[numpy.ndarray[float]]]
    """
    flattened = flatten_image_matrix(image_values)
    count = 0
    # M step, random prototype vector
    if initial_means == None:
        initial_means_idx = np.random.choice(flattened.shape[0],
                                             k,
                                             replace=False)
        mu_k = flattened[initial_means_idx]
    else:
        mu_k = initial_means

    while count < 1:
        # E step - updating r_nk
        squared_dist = np.array([
            np.square(flattened - mu_k[i]).sum(axis=1)
            for i in range(mu_k.shape[0])
        ])
        r_nk = np.argmin(squared_dist, axis=0)
        # M step - update mu_k
        clusters = np.array([flattened[(r_nk == i)] for i in range(k)])
        mu_k_prev = mu_k
        mu_k = np.array([clusters[i].mean(axis=0) for i in range(k)])
        # Convergence test
        if np.array_equal(mu_k_prev, mu_k):
            count += 1

    image_matrix = np.array([mu_k[k] for k in r_nk])
    updated_image_values = unflatten_image_matrix(image_matrix,
                                                  image_values.shape[1])
    return updated_image_values
    raise NotImplementedError()
Exemplo n.º 11
0
    def __init__(self, image_matrix, num_components, means=None):
        """
        Initialize a Gaussian mixture model.

        params:
        image_matrix = (grayscale) numpy.nparray[numpy.nparray[float]]
        num_components = int
        """
        self.image_matrix = image_matrix
        self.flatten_image = flatten_image_matrix(self.image_matrix)
        self.num_components = num_components
        if (means is None):
            self.means = np.zeros(num_components)
        else:
            self.means = means
        self.variances = np.zeros(num_components)
        self.mixing_coefficients = np.zeros(num_components)
        ind = np.where(self.flatten_image < 0)
        self.flatten_image[ind] = 10e-9
Exemplo n.º 12
0
    def initialize_training(self):
        """
        Initialize the training
        process by setting each
        component mean using some algorithm that
        you think might give better means to start with,
        each component variance to 1, and
        each component mixing coefficient
        to a uniform value
        (e.g. 4 components -> [0.25,0.25,0.25,0.25]).
        [You can feel free to modify the variance and mixing coefficient
         initializations too if that works well.]
        """
        flattened = flatten_image_matrix(self.image_matrix)
        count = 0
        k = self.num_components
        # M step, random prototype vector
        initial_means_idx = np.random.choice(flattened.shape[0],
                                             k,
                                             replace=False)
        mu_k = flattened[initial_means_idx]

        while count < 1:
            # E step - updating r_nk
            squared_dist = np.array([
                np.square(flattened - mu_k[i]).sum(axis=1)
                for i in range(mu_k.shape[0])
            ])
            r_nk = np.argmin(squared_dist, axis=0)
            # M step - update mu_k
            clusters = np.array([flattened[r_nk == i] for i in range(k)])
            mu_k_prev = mu_k
            mu_k = np.array([clusters[i].mean(axis=0) for i in range(k)])
            # Convergence test
            if np.array_equal(mu_k_prev, mu_k):
                count += 1
        #print(1/self.num_components)
        mixing_coefficient = 1.0 / self.num_components
        self.means = mu_k.tolist()
        self.variances = [1] * self.num_components
        self.mixing_coefficients = [mixing_coefficient] * self.num_components
Exemplo n.º 13
0
    def initialize_training(self):
        """
        Initialize the training
        process by setting each
        component mean to a random
        pixel's value (without replacement),
        each component variance to 1, and
        each component mixing coefficient
        to a uniform value
        (e.g. 4 components -> [0.25,0.25,0.25,0.25]).

        NOTE: this should be called before
        train_model() in order for tests
        to execute correctly.
        """
        flattened = flatten_image_matrix(self.image_matrix)
        rand_idx = np.random.choice(flattened.shape[0],
                                    self.num_components,
                                    replace=False)
        self.means = flattened[rand_idx]  #.tolist()
        self.variances = np.ones(self.num_components)
        self.mixing_coefficients = np.full(self.num_components,
                                           1 / self.num_components)
Exemplo n.º 14
0
    def __init__(self, image_matrix, num_components, means=None):
        """
        Initialize a Gaussian mixture model.

        params:
        image_matrix = (grayscale) numpy.nparray[numpy.nparray[float]]
        num_components = int
        """
        # self.image_matrix = image_matrix
        # self.num_components = num_components
        # if(means is None):
        #     self.means = [0]*num_components
        # else:
        #     self.means = means
        # self.variances = [0]*num_components
        # self.mixing_coefficients = [0]*num_components
        self.image_matrix = image_matrix
        self.num_components = num_components
        self.means = np.array(
            [0] * num_components) if means is None else np.array(means)
        self.variances = np.array([0] * num_components)
        self.mixing_coefficients = np.array([0] * num_components)
        self.flatten_image = flatten_image_matrix(self.image_matrix)
Exemplo n.º 15
0
    def initialize_training(self):
        """
        Initialize the training
        process by setting each
        component mean to a random
        pixel's value (without replacement),
        each component variance to 1, and
        each component mixing coefficient
        to a uniform value
        (e.g. 4 components -> [0.25,0.25,0.25,0.25]).

        NOTE: this should be called before
        train_model() in order for tests
        to execute correctly.
        """
        # TODO: finish this
        flatten_image = flatten_image_matrix(self.image_matrix)
        dim = flatten_image.shape
        indx = np.random.choice(dim[0], self.num_components, replace=0)
        self.means = flatten_image[indx]
        self.variances = np.ones(self.num_components, dtype=float)
        self.mixing_coefficients = np.multiply(
            np.ones(self.num_components, dtype=float),
            1 / float(self.num_components))
Exemplo n.º 16
0
    def train_model(self, convergence_function=default_convergence):
        """
        Train the mixture model
        using the expectation-maximization
        algorithm. Since each Gaussian is
        a combination of mean and variance,
        this will fill self.means and
        self.variances, plus
        self.mixing_coefficients, with
        the values that maximize
        the overall model likelihood.

        params:
        convergence_function = function, returns True if convergence is reached
        """
        flattened = flatten_image_matrix(self.image_matrix)  # n X 1
        conv_ctr = 0

        #print(self.means)
        #print(self.variances)
        def component_joint_prob(i):
            a = 0.5 * np.log(2 * np.pi * self.variances[i])
            b = (np.square(flattened - self.means[i])) / (2 *
                                                          self.variances[i])
            c = np.log(self.mixing_coefficients[i])
            return -a - b + c

        while conv_ctr < 10:
            prev_likelihood = self.likelihood()  #+ 150
            prev_variables = np.array([
                np.array(self.means).tolist(),
                np.array(self.variances).tolist(),
                np.array(self.mixing_coefficients).tolist()
            ])
            # formulae Bishop equation 9.23
            z = np.array([
                component_joint_prob(i) for i in range(self.num_components)
            ])  # 3 X n
            gamma_nk_denom = logsumexp(z, axis=0)
            for k in range(self.num_components):
                # E step
                gamma_nk_nomin = z[k]
                #print(z[k])
                gamma_nk = np.exp(gamma_nk_nomin - gamma_nk_denom)
                N_k = gamma_nk.sum()
                #print("array_constant_N_k")
                #print(N_k)
                # M step
                mu_k = np.multiply(gamma_nk, flattened).sum() / N_k
                x_muk = flattened - mu_k
                sigma_k = np.multiply(
                    gamma_nk, np.square(x_muk)).sum() / N_k  #covar matrix
                #print(gamma_nk.shape)
                #print("diff shape")
                #print((flattened - mu_k).shape)
                pi_k = N_k / flattened.shape[0]
                # update
                self.means[k] = mu_k
                self.variances[k] = sigma_k
                self.mixing_coefficients[k] = pi_k

            new_likelihood = self.likelihood()  #+ 150
            new_variables = np.array([
                np.array(self.means).tolist(),
                np.array(self.variances).tolist(),
                np.array(self.mixing_coefficients).tolist()
            ])
            if convergence_function == default_convergence:
                conv_ctr, converge_bool = convergence_function(prev_likelihood,
                                                               new_likelihood,
                                                               conv_ctr,
                                                               conv_ctr_cap=10)
            else:
                conv_ctr, converge_bool = convergence_function(prev_variables,
                                                               new_variables,
                                                               conv_ctr,
                                                               conv_ctr_cap=10)