def main(): ############################################################################# # first we'll visualize different solutions found uniform scalar quantization # as well as by the 4 variants of Lloyd that all have similar rates ############################################################################# random_laplacian_samps = np.random.laplace(scale=10, size=(50000, 2)) dummy_data = np.copy(random_laplacian_samps) dummy_data[:, 1] = (np.abs(random_laplacian_samps[:, 0]) + random_laplacian_samps[:, 1]) ############################################################ # Uniform scalar quantization of each coefficient separately BINWIDTH_COMPONENT_0 = 11. BINWIDTH_COMPONENT_1 = 11. starttime = time.time() uni_apts_s0, uni_assignments_s0, uni_MSE_s0, uni_rate_s0 = uni( dummy_data[:, 0], BINWIDTH_COMPONENT_0, placement_scheme='on_mode') uni_apts_s1, uni_assignments_s1, uni_MSE_s1, uni_rate_s1 = uni( dummy_data[:, 1], BINWIDTH_COMPONENT_1, placement_scheme='on_mode') print("Time to compute uniform scalar quantizations:", time.time() - starttime) uni_fig_s0 = plot_1d_and_2d_assignments( uni_apts_s0, dummy_data[:, 0], uni_assignments_s0, 'uniform_scalar', 100, title='Uniform scalar quantization, component 0') uni_fig_s1 = plot_1d_and_2d_assignments( uni_apts_s1, dummy_data[:, 1], uni_assignments_s1, 'uniform_scalar', 100, title='Uniform scalar quantization, component 1') print('The rate for the uniform scalar quantizer is', (uni_rate_s0 + uni_rate_s1) / 2, 'bits per component') print('The MSE for the uniform scalar quantizer is', (uni_MSE_s0 + uni_MSE_s1) / 2, 'luminace units per component') print('===========================') def get_init_assignments_for_lloyd(data, the_binwidths): # Lloyd can run into trouble if the most extreme assignment points are # larger in magnitude than the most extreme datapoints, which can happen # with the uniform quantization, so we just get rid of those initial points. assgnmnts, _, _, _ = uni(data, the_binwidths, placement_scheme='on_mode') min_data = np.min(data, axis=0) max_data = np.max(data, axis=0) if data.ndim == 1: assgnmnts = np.delete(assgnmnts, np.where(assgnmnts < 0.9 * min_data)) assgnmnts = np.delete(assgnmnts, np.where(assgnmnts > 0.9 * max_data)) return assgnmnts else: mask_min = np.any(assgnmnts[:, :] < 0.9 * min_data[None, :], axis=1) mask_max = np.any(assgnmnts[:, :] > 0.9 * max_data[None, :], axis=1) assgnmnts = np.delete(assgnmnts, np.where(mask_min + mask_max), axis=0) return assgnmnts ########################################################## # Lloyd scalar quantization of each coefficient separately INIT_BW_C0 = 27 # we need way fewer in this case, bigger starting bins INIT_BW_C1 = 27 starttime = time.time() init_assignments = get_init_assignments_for_lloyd(dummy_data[:, 0], INIT_BW_C0) gl_apts_s0, gl_assignments_s0, gl_MSE_s0, gl_rate_s0 = gl( dummy_data[:, 0], init_assignments) init_assignments = get_init_assignments_for_lloyd(dummy_data[:, 1], INIT_BW_C1) gl_apts_s1, gl_assignments_s1, gl_MSE_s1, gl_rate_s1 = gl( dummy_data[:, 1], init_assignments) print("Time to compute separate (suboptimal) scalar quantizations:", time.time() - starttime) gl_fig_s0 = plot_1d_and_2d_assignments( gl_apts_s0, dummy_data[:, 0], gl_assignments_s0, 'lloyd_scalar', 100, title='Suboptimal Lloyd scalar quantization, component 0') gl_fig_s1 = plot_1d_and_2d_assignments( gl_apts_s1, dummy_data[:, 1], gl_assignments_s1, 'lloyd_scalar', 100, title='Suboptimal Lloyd scalar quantization, component 1') print('The rate for the suboptimal scalar Lloyd quantizer is', (gl_rate_s0 + gl_rate_s1) / 2, 'bits per component') print('The MSE for the suboptial scalar Lloyd quantizer is', (gl_MSE_s0 + gl_MSE_s1) / 2, 'luminace units per component') print('===========================') ############################################################################# # we'll try Lloyd scalar quantization again but this time the optimal version INIT_BW_C0 = 20 INIT_BW_C1 = 20 #^ We'll give ourselves more clusters, but turn up the lambda and these will # be pruned down. After some trial and error these settings give us something # close to the rate of the non-optimal version starttime = time.time() init_assignments = get_init_assignments_for_lloyd(dummy_data[:, 0], INIT_BW_C0) init_cword_len = (-1. * np.log2(1. / len(init_assignments)) * np.ones( (len(init_assignments), ))) opt_gl_apts_s0, opt_gl_assignments_s0, opt_gl_MSE_s0, opt_gl_rate_s0 = \ opt_gl(dummy_data[:, 0], init_assignments, init_cword_len, lagrange_mult=0.6) init_assignments = get_init_assignments_for_lloyd(dummy_data[:, 1], INIT_BW_C1) init_cword_len = (-1. * np.log2(1. / len(init_assignments)) * np.ones( (len(init_assignments), ))) opt_gl_apts_s1, opt_gl_assignments_s1, opt_gl_MSE_s1, opt_gl_rate_s1 = \ opt_gl(dummy_data[:, 1], init_assignments, init_cword_len, lagrange_mult=0.6) print("Time to compute separate (optimal) scalar quantizations:", time.time() - starttime) opt_gl_fig_s0 = plot_1d_and_2d_assignments( opt_gl_apts_s0, dummy_data[:, 0], opt_gl_assignments_s0, 'optimal_lloyd_scalar', 100, title='Optimal Lloyd scalar quantization, component 0') opt_gl_fig_s1 = plot_1d_and_2d_assignments( opt_gl_apts_s1, dummy_data[:, 1], opt_gl_assignments_s1, 'optimal_lloyd_scalar', 100, title='Optimal Lloyd scalar quantization, component 1') print('The rate for the optimal scalar Lloyd quantizer is', (opt_gl_rate_s0 + opt_gl_rate_s1) / 2, 'bits per component') print('The MSE for the optimal scalar Lloyd quantizer is', (opt_gl_MSE_s0 + opt_gl_MSE_s1) / 2, 'luminace units per component') print('===========================') # ########################################## # Now we can try Uniform VECTOR quantization BINWIDTHS = np.array([10., 10.]) starttime = time.time() uni_2d_apts, uni_2d_assignments, uni_2d_MSE, uni_2d_rate = uni( dummy_data, BINWIDTHS, placement_scheme='on_mode') print("Time to compute uniform vector quantizations:", time.time() - starttime) uni_2d_fig_s0 = plot_1d_and_2d_assignments( uni_2d_apts, dummy_data, uni_2d_assignments, 'uniform_vector', 100, title='Uniform vector quantization') print('The rate for the uniform vector quantizer is', uni_2d_rate / 2, 'bits per component') print('The MSE for the uniform vector quantizer is', uni_2d_MSE / 2, 'luminace units per component') print('===========================') ########################################################################## # Now we use the generalized Lloyd to do joint encoding of both components BINWIDTHS = np.array([29., 30.]) starttime = time.time() init_assignments = get_init_assignments_for_lloyd(dummy_data, BINWIDTHS) gl_2d_apts, gl_2d_assignments, gl_2d_MSE, gl_2d_rate = gl( dummy_data, init_assignments) print("Time to compute 2d (suboptimal) vector quantization:", time.time() - starttime) gl_2d_fig = plot_1d_and_2d_assignments( gl_2d_apts, dummy_data, gl_2d_assignments, 'lloyd_vector', 100, title='Generalized (vector) Lloyd quantization') print('The rate for the suboptimal 2d Lloyd quantizer is', gl_2d_rate / 2, 'bits per component') print('The MSE for the suboptimal 2d Lloyd quantizer is', gl_2d_MSE / 2, 'luminace units per component') print('===========================') ####################################################### # We can compare this to the optimal generalized Lloyd BINWIDTHS = np.array([23., 24.]) starttime = time.time() init_assignments = get_init_assignments_for_lloyd(dummy_data, BINWIDTHS) init_cword_len = (-1. * np.log2(1. / len(init_assignments)) * np.ones( (len(init_assignments), ))) opt_gl_2d_apts, opt_gl_2d_assignments, opt_gl_2d_MSE, opt_gl_2d_rate = \ opt_gl(dummy_data, init_assignments, init_cword_len, lagrange_mult=0.1) print("Time to compute 2d (optimal) vector quantization:", time.time() - starttime) opt_gl_2d_fig = plot_1d_and_2d_assignments( opt_gl_2d_apts, dummy_data, opt_gl_2d_assignments, 'optimal_lloyd_vector', 100, title='Optimal generalized (vector) Lloyd quantization') print('The rate for the optimal 2d Lloyd quantizer is', opt_gl_2d_rate / 2, 'bits per component') print('The MSE for the optimal 2d Lloyd quantizer is', opt_gl_2d_MSE / 2, 'luminace units per component') plt.show() ########################################################################## # Okay, now let's sweep out some rate-distortion curves using this dataset ########################################################################## # uniform scalar first uni_rates = [] uni_MSEs = [] for binwidth in np.linspace(4, 32, 50): _, _, uni_MSE_s0, uni_rate_s0 = uni(dummy_data[:, 0], binwidth, placement_scheme='on_mode') _, _, uni_MSE_s1, uni_rate_s1 = uni(dummy_data[:, 1], binwidth, placement_scheme='on_mode') uni_rates.append((uni_rate_s0 + uni_rate_s1) / 2) uni_MSEs.append((uni_MSE_s0 + uni_MSE_s1) / 2) # for the Lloyd curves I'm going to start the initialization in exactly # the same places as the uniform so we can see the improvement that Optimal # Lloyd provides # suboptimal scalar Lloyd gl_rates = [] gl_MSEs = [] for binwidth in np.linspace(4, 32, 50): print('RD curve, suboptimal scalar lloyd, binwidth=', binwidth) init_assignments, _, _, _ = uni(dummy_data[:, 0], binwidth, placement_scheme='on_mode') _, _, gl_MSE_s0, gl_rate_s0 = gl(dummy_data[:, 0], init_assignments, force_const_num_assignment_pts=False) #^ make this correspond to optimal lloyd with lambda=0.0. init_assignments, _, _, _ = uni(dummy_data[:, 1], binwidth, placement_scheme='on_mode') _, _, gl_MSE_s1, gl_rate_s1 = gl(dummy_data[:, 1], init_assignments, force_const_num_assignment_pts=False) #^ make this correspond to optimal lloyd with lambda=0.0. gl_rates.append((gl_rate_s0 + gl_rate_s1) / 2) gl_MSEs.append((gl_MSE_s0 + gl_MSE_s1) / 2) # next optimal scalar Lloyd opt_gl_rates = [] opt_gl_MSEs = [] binwidth = 4 for lagrange_w in np.linspace(0.0, 4.0, 50): print('RD curve, optimal scalar lloyd, lagrange mult=', lagrange_w) init_assignments, _, _, _ = uni(dummy_data[:, 0], binwidth, placement_scheme='on_mode') init_cword_len = (-1. * np.log2(1. / len(init_assignments)) * np.ones( (len(init_assignments), ))) _, _, opt_gl_MSE_s0, opt_gl_rate_s0 = opt_gl(dummy_data[:, 0], init_assignments, init_cword_len, lagrange_mult=lagrange_w) init_assignments, _, _, _ = uni(dummy_data[:, 1], binwidth, placement_scheme='on_mode') init_cword_len = (-1. * np.log2(1. / len(init_assignments)) * np.ones( (len(init_assignments), ))) _, _, opt_gl_MSE_s1, opt_gl_rate_s1 = opt_gl(dummy_data[:, 1], init_assignments, init_cword_len, lagrange_mult=lagrange_w) opt_gl_rates.append((opt_gl_rate_s0 + opt_gl_rate_s1) / 2) opt_gl_MSEs.append((opt_gl_MSE_s0 + opt_gl_MSE_s1) / 2) # plot the three scalar variants plt.figure(figsize=(20, 20)) plt.plot(uni_MSEs, uni_rates, label='Uniform Scalar', linewidth=4) plt.plot(gl_MSEs, gl_rates, label='Suboptimal Scalar Lloyd', linewidth=4) plt.plot(opt_gl_MSEs, opt_gl_rates, label='Optimal Scalar Lloyd', linewidth=4) plt.legend(fontsize=15) plt.title('Rate-distortion performance of different scalar quantization ' + 'schemes', fontsize=20) plt.xlabel('Distortion (Mean squared error)', fontsize=15) plt.ylabel('Rate (bits per component)', fontsize=15) # next uniform vector (2d) uni_2d_rates = [] uni_2d_MSEs = [] for binwidth in np.linspace(8, 32, 50): _, _, uni_2d_MSE, uni_2d_rate = uni(dummy_data, np.array([binwidth, binwidth]), placement_scheme='on_mode') uni_2d_rates.append(uni_2d_rate / 2) uni_2d_MSEs.append(uni_2d_MSE / 2) # next suboptimal generalized Lloyd (2d) gl_2d_rates = [] gl_2d_MSEs = [] for binwidth in np.linspace(8, 60, 50): print('RD curve, suboptimal vector Lloyd, binwidth=', binwidth) init_assignments, _, _, _ = uni(dummy_data, np.array([binwidth, binwidth]), placement_scheme='on_mode') _, _, gl_2d_MSE, gl_2d_rate = gl(dummy_data, init_assignments, force_const_num_assignment_pts=False) #^ make this correspond to optimal lloyd with lambda=0.0. gl_2d_rates.append(gl_2d_rate / 2) gl_2d_MSEs.append(gl_2d_MSE / 2) # finally, the optimal generalized Lloyd opt_gl_2d_rates = [] opt_gl_2d_MSEs = [] binwidth = 8 for lagrange_w in np.linspace(0.0, 4.0, 50): print('RD curve, optimal vector Lloyd, lagrange mult=', lagrange_w) init_assignments, _, _, _ = uni(dummy_data, np.array([binwidth, binwidth]), placement_scheme='on_mode') init_cword_len = (-1. * np.log2(1. / len(init_assignments)) * np.ones( (len(init_assignments), ))) _, _, opt_gl_2d_MSE, opt_gl_2d_rate = opt_gl(dummy_data, init_assignments, init_cword_len, lagrange_mult=lagrange_w) opt_gl_2d_rates.append(opt_gl_2d_rate / 2) opt_gl_2d_MSEs.append(opt_gl_2d_MSE / 2) # plot the three 2D variants plt.figure(figsize=(20, 20)) plt.plot(uni_2d_MSEs, uni_2d_rates, label='Uniform 2D', linewidth=4) plt.plot(gl_2d_MSEs, gl_2d_rates, label='Suboptimal 2D Lloyd', linewidth=4) plt.plot(opt_gl_2d_MSEs, opt_gl_2d_rates, label='Optimal 2D Lloyd', linewidth=4) plt.legend(fontsize=15) plt.title('Rate-distortion performance of different vector quantization ' + 'schemes', fontsize=20) plt.xlabel('Distortion (Mean squared error)', fontsize=15) plt.ylabel('Rate (bits per component)', fontsize=15) # plot all the variants together plt.figure(figsize=(20, 20)) plt.plot(uni_MSEs, uni_rates, label='Uniform Scalar', linewidth=4) plt.plot(gl_MSEs, gl_rates, label='Suboptimal Scalar Lloyd', linewidth=4) plt.plot(opt_gl_MSEs, opt_gl_rates, label='Optimal Scalar Lloyd', linewidth=4) plt.plot(uni_2d_MSEs, uni_2d_rates, label='Uniform 2D', linewidth=4) plt.plot(gl_2d_MSEs, gl_2d_rates, label='Suboptimal 2D Lloyd', linewidth=4) plt.plot(opt_gl_2d_MSEs, opt_gl_2d_rates, label='Optimal 2D Lloyd', linewidth=4) plt.legend(fontsize=15) plt.title('Rate-distortion performance of 4 variants ' + 'of Lloyd/LBG\nplus 2 variants of uniform quantization', fontsize=20) plt.xlabel('Distortion (Mean squared error)', fontsize=15) plt.ylabel('Rate (bits per component)', fontsize=15) plt.show()
random_laplacian_samps[:, i]) ####################################################### # We can compare this to the optimal generalized Lloyd BINWIDTHS = 23 + np.arange(ndims)/ndims starttime = time.time() print("Getting initial assignments...") init_assignments = get_init_assignments_for_lloyd(dummy_data, BINWIDTHS) init_cword_len = (-1. * np.log2(1. / len(init_assignments)) * np.ones((len(init_assignments),))) print("Time to compute initial assignment points:", time.time() - starttime) print("computing optimal lloyd quantization...") # Numpy opt_gl_nd_apts, opt_gl_nd_assignments, opt_gl_nd_MSE, opt_gl_nd_rate = \ opt_gl(dummy_data, init_assignments, init_cword_len, lagrange_mult=0.1, nn_method='brute_break') # Torch opt_gl_nd_apts, opt_gl_nd_assignments, opt_gl_nd_MSE, opt_gl_nd_rate = \ opt_gl_torch(dummy_data, init_assignments, init_cword_len, lagrange_mult=0.1, device=device, nn_method='brute_break') print("Time to compute {}d (optimal) vector quantization:".format(ndims), time.time() - starttime) print("{}d MSE per dimension".format(ndims),opt_gl_nd_MSE/ndims) print("{}d rate per dimension".format(ndims),opt_gl_nd_rate/ndims)