Q:

Eliminate consecutive duplicates

Eliminate consecutive duplicates of list elements.
My solution for this is:
compress([X,X|Xs], Q) :-
   compress([X|Xs], Q).
compress([X,Y|Xs], Q) :-
   X \= Y,
   compress([Y|Xs], QR),
   append([X], QR, Q).
compress([X|[]], Q) :-
   compress([], QR),
   append([X], QR, Q).
compress([], []).

And, because of the fact I am beginner and I have no experience in a logic paradigm I ask you for say what I can improve and why my solution is not good as it can be.
For example, X \= Y doesn't look pretty to me.

A:

We start with the name of the predicate.
Why do you use an imperative to denote a relation? A good Prolog program is usable in all directions, whereas an imperative always suggests a particular direction or mode of use. Therefore, choose a declarative name and aim for generality and logical-purity.
Next, what about the most general query:
?- compress(Ls, Cs).
ERROR: Out of local stack

Not very nice! We expect this to yield at least a few answers.
What if we use iterative deepening:

?- length(Ls, _), compress(Ls, Cs).
Ls = Cs, Cs = [] ;
Ls = Cs, Cs = [_G841] ;
Ls = [_G841, _G841],
Cs = [_G841] ;
Ls = [_G841, _G841, _G841],
Cs = [_G841] .

Hm! Quite a few answers are missing! What about the case where the elements are different? As you already intuitively expect, it is the use of impure predicates that leads to such effects.
Therefore, use prolog-dif, i.e., dif/2, to denote that two terms are different. It's usable in all directions!
Moreover, DCGs (dcg) are often useful when describing lists.
So, in total, what about this:

compression([])     --> [].
compression([L|Ls]) --> [L], compression_(Ls, L).

compression_([], _) --> [].
compression_([X|Xs], L) -->
        (   { X = L },
            compression_(Xs, L)
        ;   { dif(X, L) },
            [X],
            compression_(Xs, X)
        ).

We use the interface predicate phrase/2 to work with the DCG.
Usage examples:

?- phrase(compression(Ls), Cs).
Ls = Cs, Cs = [] ;
Ls = Cs, Cs = [_G815] ;
Ls = [_G815, _G815],
Cs = [_G815] .

?- length(Ls, _), phrase(compression(Ls), Cs).
Ls = Cs, Cs = [] ;
Ls = Cs, Cs = [_G865] ;
Ls = [_G865, _G865],
Cs = [_G865] ;
Ls = Cs, Cs = [_G1111, _G1114],
dif(_G1114, _G1111) .

Take it from here! Improve determinism, find an even better name etc.

A:

Building on the answer by @mat (+1), why not improve determinacy for cases like this one:

?- phrase(compression([a,a,b,b,b,c,c,c,c,d]), Xs).
Xs = [a, b, c, d] ;
false.

With ; false the SWI prolog-toplevel indicates that the goal did not succeed deterministically.
We can improve compression_//2 by using if_//3—the dcg analogue of if_/3:

compression_([], _) --> [].
compression_([X|Xs], L) -->
   if_(X = L,                           % is this item equal to previous one?
       compression_(Xs, L),             %   yes: old "run" goes on
       ([X], compression_(Xs, X))).     %    no: new "run" starts

Sample query:
?- phrase(compression([a,a,b,b,b,c,c,c,c,d]), Xs).
Xs = [a, b, c, d].                            % succeeds deterministically

