Exemplo n.º 1
0
    def plot_distribution(self):
        "Plot histogram of # classes in an image. Return the figure."
        table = self.get_cls_ground_truth(with_diff=False, with_trun=True)
        fig = plt.figure()
        ax = fig.add_subplot(111)
        bins = np.arange(1, max(table.sum(1)) + 2)
        ax.hist(table.sum(1), bins, align="left", normed=True)
        ax.set_xticks(bins)
        ax.set_xlabel("Number of classes present in the image")
        ax.grid(False)

        dirname = config.get_dataset_stats_dir(self)
        filename = opjoin(dirname, "num_classes.png")
        fig.savefig(filename)
        return fig
Exemplo n.º 2
0
    def plot_distribution(self):
        "Plot histogram of # classes in an image. Return the figure."
        table = self.get_cls_ground_truth(with_diff=False, with_trun=True)
        fig = plt.figure()
        ax = fig.add_subplot(111)
        bins = np.arange(1, max(table.sum(1)) + 2)
        ax.hist(table.sum(1), bins, align='left', normed=True)
        ax.set_xticks(bins)
        ax.set_xlabel('Number of classes present in the image')
        ax.grid(False)

        dirname = config.get_dataset_stats_dir(self)
        filename = opjoin(dirname, 'num_classes.png')
        fig.savefig(filename)
        return fig
Exemplo n.º 3
0
    def plot_coocurrence(
        self,
        cmap=plt.cm.Reds,
        color_anchor=[0, 1],
        x_tick_rot=90,
        size=None,
        title=None,
        plot_vals=True,
        second_order=False,
    ):
        """
    Plot a heat map of conditional occurence, where cell (i,j) means
    P(C_j|C_i). The last column in the K x (K+2) heat map corresponds
    to the prior P(C_i).

    If second_order, plots (K choose 2) x (K+2) heat map corresponding
    to P(C_i|C_j,C_k): second-order correlations.

    Return the figure.
    """
        table = self.get_cls_ground_truth(with_diff=False, with_trun=True)

        # This takes care of most of the difference between normal and second_order
        # In the former case, a "combination" is just one class to condition on.
        combinations = combination_strs = table.cols
        if second_order:
            combinations = [x for x in itertools.combinations(table.cols, 2)]
            combination_strs = ["%s, %s" % (x[0], x[1]) for x in combinations]

        total = table.shape[0]
        N = len(table.cols)
        K = len(combinations)
        data = np.zeros((K, N + 2))  # extra columns are for P("nothing"|C) and P(C)
        prior = np.zeros(K)
        for i, combination in enumerate(combinations):
            if second_order:
                cls1 = combination[0]
                cls2 = combination[1]
                conditioned = table.filter_on_column(cls1).filter_on_column(cls2)
            else:
                conditioned = table.filter_on_column(combination)

            # count all the classes
            data[i, :-2] = conditioned.sum()

            # count the number of times that cls was the only one present to get
            # P("nothing"|C)
            if second_order:
                data[i, -2] = ((conditioned.sum(1) - 2) == 0).sum()
            else:
                data[i, -2] = ((conditioned.sum(1) - 1) == 0).sum()

            # normalize
            max_val = np.max(data[i, :])
            data[i, :] /= max_val
            data[i, :][data[i, :] == 1] = np.nan

            # use the max count to compute the prior
            data[i, -1] = max_val / total

            m = Table(data, table.cols + ["nothing", "prior"], index=combination_strs)

        # If second_order, sort by prior and remove rows with 0 prior
        if second_order:
            m = m.filter_on_column("prior", 0.001, operator.gt).sort_by_column("prior", descending=True)
            # TODO: just take the top K actually, for a side-by-side figure
            m.arr = m.arr[: len(self.classes), :]

        if size:
            fig = plt.figure(figsize=size)
        else:
            w = max(12, m.shape[1])
            h = max(12, m.shape[0])
            fig = plt.figure(figsize=(w, h))
        ax_im = fig.add_subplot(111)

        # make axes for colorbar
        divider = make_axes_locatable(ax_im)
        ax_cb = divider.new_vertical(size="5%", pad=0.1, pack_start=True)
        fig.add_axes(ax_cb)

        # The call to imshow produces the matrix plot:
        im = ax_im.imshow(
            m.arr, origin="upper", interpolation="nearest", vmin=color_anchor[0], vmax=color_anchor[1], cmap=cmap
        )

        # Formatting:
        ax = ax_im
        ax.set_xticks(np.arange(m.shape[1]))
        ax.set_xticklabels(m.cols)
        for tick in ax.xaxis.iter_ticks():
            tick[0].label2On = True
            tick[0].label1On = False
            tick[0].label2.set_rotation(x_tick_rot)
            tick[0].label2.set_fontsize("x-large")

        ax.set_yticks(np.arange(m.shape[0]))
        ax.set_yticklabels(m.index, size="x-large")

        ax.yaxis.set_minor_locator(matplotlib.ticker.FixedLocator(np.arange(-0.5, m.shape[0] + 0.5)))
        ax.xaxis.set_minor_locator(matplotlib.ticker.FixedLocator(np.arange(-0.5, m.shape[1] - 0.5)))
        ax.grid(False, which="major")
        ax.grid(True, which="minor", ls="-", lw=7, c="w")

        # Make the major and minor tick marks invisible
        for line in ax.xaxis.get_ticklines() + ax.yaxis.get_ticklines():
            line.set_markeredgewidth(0)
        for line in ax.xaxis.get_minorticklines() + ax.yaxis.get_minorticklines():
            line.set_markeredgewidth(0)

        # Limit the area of the plot
        ax.set_ybound([-0.5, m.shape[0] - 0.5])
        ax.set_xbound([-0.5, m.shape[1] - 0.5])

        # The following produces the colorbar and sets the ticks
        # Set the ticks - if 0 is in the interval of values, set that, as well
        # as the maximal and minimal values:
        # Extract the minimum and maximum values for scaling
        max_val = np.nanmax(m.arr)
        min_val = np.nanmin(m.arr)
        if min_val < 0:
            ticks = [color_anchor[0], min_val, 0, max_val, color_anchor[1]]
        # Otherwise - only set the maximal value:
        else:
            ticks = [color_anchor[0], max_val, color_anchor[1]]

        # Plot line separating 'nothing' and 'prior' from rest of plot
        l = ax.add_line(
            mpl.lines.Line2D([m.shape[1] - 2.5, m.shape[1] - 2.5], [-0.5, m.shape[0] - 0.5], ls="--", c="gray", lw=2)
        )
        l.set_zorder(3)

        # Display the actual values in the cells
        if plot_vals:
            for i in xrange(0, m.shape[0]):
                for j in xrange(0, m.shape[1]):
                    val = m.arr[i, j]
                    if np.isnan(val):
                        continue
                    if val > 0.5:
                        ax.text(j - 0.2, i + 0.1, "%.2f" % val, color="w")
                    else:
                        ax.text(j - 0.2, i + 0.1, "%.2f" % val, color="k")

        # Hide the black frame around the plot
        # Doing ax.set_frame_on(False) results in weird thin lines
        # from imshow() at the edges. Instead, we set the frame to white.
        for spine in ax.spines.values():
            spine.set_edgecolor("w")

        # Set title
        if title is not None:
            ax.set_title(title)

        # Plot the colorbar and remove its frame as well.
        cb = fig.colorbar(im, cax=ax_cb, orientation="horizontal", cmap=cmap, ticks=ticks, format="%.2f")
        cb.ax.artists.remove(cb.outline)

        # Save figure
        dirname = config.get_dataset_stats_dir(self)
        suffix = "_second_order" if second_order else ""
        filename = opjoin(dirname, "cooccur%s.png" % suffix)
        fig.savefig(filename)

        return fig
Exemplo n.º 4
0
    def plot_coocurrence(self,
                         cmap=plt.cm.Reds,
                         color_anchor=[0, 1],
                         x_tick_rot=90,
                         size=None,
                         title=None,
                         plot_vals=True,
                         second_order=False):
        """
    Plot a heat map of conditional occurence, where cell (i,j) means
    P(C_j|C_i). The last column in the K x (K+2) heat map corresponds
    to the prior P(C_i).

    If second_order, plots (K choose 2) x (K+2) heat map corresponding
    to P(C_i|C_j,C_k): second-order correlations.

    Return the figure.
    """
        table = self.get_cls_ground_truth(with_diff=False, with_trun=True)

        # This takes care of most of the difference between normal and second_order
        # In the former case, a "combination" is just one class to condition on.
        combinations = combination_strs = table.cols
        if second_order:
            combinations = [x for x in itertools.combinations(table.cols, 2)]
            combination_strs = ['%s, %s' % (x[0], x[1]) for x in combinations]

        total = table.shape[0]
        N = len(table.cols)
        K = len(combinations)
        data = np.zeros(
            (K, N + 2))  # extra columns are for P("nothing"|C) and P(C)
        prior = np.zeros(K)
        for i, combination in enumerate(combinations):
            if second_order:
                cls1 = combination[0]
                cls2 = combination[1]
                conditioned = table.filter_on_column(cls1).filter_on_column(
                    cls2)
            else:
                conditioned = table.filter_on_column(combination)

            # count all the classes
            data[i, :-2] = conditioned.sum()

            # count the number of times that cls was the only one present to get
            # P("nothing"|C)
            if second_order:
                data[i, -2] = ((conditioned.sum(1) - 2) == 0).sum()
            else:
                data[i, -2] = ((conditioned.sum(1) - 1) == 0).sum()

            # normalize
            max_val = np.max(data[i, :])
            data[i, :] /= max_val
            data[i, :][data[i, :] == 1] = np.nan

            # use the max count to compute the prior
            data[i, -1] = max_val / total

            m = Table(data,
                      table.cols + ['nothing', 'prior'],
                      index=combination_strs)

        # If second_order, sort by prior and remove rows with 0 prior
        if second_order:
            m = m.filter_on_column('prior',0.001,operator.gt).\
                  sort_by_column('prior',descending=True)
            # TODO: just take the top K actually, for a side-by-side figure
            m.arr = m.arr[:len(self.classes), :]

        if size:
            fig = plt.figure(figsize=size)
        else:
            w = max(12, m.shape[1])
            h = max(12, m.shape[0])
            fig = plt.figure(figsize=(w, h))
        ax_im = fig.add_subplot(111)

        # make axes for colorbar
        divider = make_axes_locatable(ax_im)
        ax_cb = divider.new_vertical(size="5%", pad=0.1, pack_start=True)
        fig.add_axes(ax_cb)

        #The call to imshow produces the matrix plot:
        im = ax_im.imshow(m.arr,
                          origin='upper',
                          interpolation='nearest',
                          vmin=color_anchor[0],
                          vmax=color_anchor[1],
                          cmap=cmap)

        #Formatting:
        ax = ax_im
        ax.set_xticks(np.arange(m.shape[1]))
        ax.set_xticklabels(m.cols)
        for tick in ax.xaxis.iter_ticks():
            tick[0].label2On = True
            tick[0].label1On = False
            tick[0].label2.set_rotation(x_tick_rot)
            tick[0].label2.set_fontsize('x-large')

        ax.set_yticks(np.arange(m.shape[0]))
        ax.set_yticklabels(m.index, size='x-large')

        ax.yaxis.set_minor_locator(
            matplotlib.ticker.FixedLocator(np.arange(-.5, m.shape[0] + 0.5)))
        ax.xaxis.set_minor_locator(
            matplotlib.ticker.FixedLocator(np.arange(-.5, m.shape[1] - 0.5)))
        ax.grid(False, which='major')
        ax.grid(True, which='minor', ls='-', lw=7, c='w')

        # Make the major and minor tick marks invisible
        for line in ax.xaxis.get_ticklines() + ax.yaxis.get_ticklines():
            line.set_markeredgewidth(0)
        for line in ax.xaxis.get_minorticklines(
        ) + ax.yaxis.get_minorticklines():
            line.set_markeredgewidth(0)

        # Limit the area of the plot
        ax.set_ybound([-0.5, m.shape[0] - 0.5])
        ax.set_xbound([-0.5, m.shape[1] - 0.5])

        #The following produces the colorbar and sets the ticks
        #Set the ticks - if 0 is in the interval of values, set that, as well
        #as the maximal and minimal values:
        #Extract the minimum and maximum values for scaling
        max_val = np.nanmax(m.arr)
        min_val = np.nanmin(m.arr)
        if min_val < 0:
            ticks = [color_anchor[0], min_val, 0, max_val, color_anchor[1]]
        #Otherwise - only set the maximal value:
        else:
            ticks = [color_anchor[0], max_val, color_anchor[1]]

        # Plot line separating 'nothing' and 'prior' from rest of plot
        l = ax.add_line(
            mpl.lines.Line2D([m.shape[1] - 2.5, m.shape[1] - 2.5],
                             [-.5, m.shape[0] - 0.5],
                             ls='--',
                             c='gray',
                             lw=2))
        l.set_zorder(3)

        # Display the actual values in the cells
        if plot_vals:
            for i in xrange(0, m.shape[0]):
                for j in xrange(0, m.shape[1]):
                    val = m.arr[i, j]
                    if np.isnan(val):
                        continue
                    if val > 0.5:
                        ax.text(j - 0.2, i + 0.1, '%.2f' % val, color='w')
                    else:
                        ax.text(j - 0.2, i + 0.1, '%.2f' % val, color='k')

        # Hide the black frame around the plot
        # Doing ax.set_frame_on(False) results in weird thin lines
        # from imshow() at the edges. Instead, we set the frame to white.
        for spine in ax.spines.values():
            spine.set_edgecolor('w')

        # Set title
        if title is not None:
            ax.set_title(title)

        # Plot the colorbar and remove its frame as well.
        cb = fig.colorbar(im,
                          cax=ax_cb,
                          orientation='horizontal',
                          cmap=cmap,
                          ticks=ticks,
                          format='%.2f')
        cb.ax.artists.remove(cb.outline)

        # Save figure
        dirname = config.get_dataset_stats_dir(self)
        suffix = '_second_order' if second_order else ''
        filename = opjoin(dirname, 'cooccur%s.png' % suffix)
        fig.savefig(filename)

        return fig